Redis常见问题穿透、击穿、雪崩处理方案
发布日期:2021-11-15 14:57:37
浏览次数:33
分类:技术文章
本文共 2502 字,大约阅读时间需要 8 分钟。
缓存穿透
问题描述
一个一定不存在缓存及查询不到的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。
解决方案
- 采用布隆过滤器
- 将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力
- 空结果进行缓存
- 如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。
@Override public ArticleVO getArticle(Long articleId) { // 缓存key String cacheKey = "article:" + articleId; // 判断缓存中是否存在key if(redisTemplate.hasKey(cacheKey)){ // 从缓存中获取文章 return redisTemplate.opsForValue().get(cacheKey); } // 开始数据库查询 ArticleVO article = articleDao.queryById(articleId); if (article != null) { // 数据不为空,放入缓存 redisTemplate.opsForValue().set(cacheKey, article, 60, TimeUnit.MINUTES); } else { // 数据为空,设置默认值,放入换存,设置较短的时间 redisTemplate.opsForValue().set(cacheKey, null, 5, TimeUnit.MINUTES); } return article; }
缓存击穿
问题描述
缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库。
解决方案
- 可以将热点数据设置为永远不过期
- 实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其它请求才能通过该 key 访问数据
加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量。假设在高并发下,缓存重建期间key是锁着的,这是过来1000个请求999个都在阻塞的。同样会导致用户等待超时,这是个治标不治本的方法!
参考:
@Override public ArticleVO getArticle(Long articleId) { // 缓存key String cacheKey = "article:" + articleId; // 判断缓存中是否存在key if(redisTemplate.hasKey(cacheKey)){ // 从缓存中获取文章 return redisTemplate.opsForValue().get(cacheKey); } try { // 获取锁 boolean lock = redisLock.lock(cacheKey, articleId); if(!lock) { // 获取锁失败,返回空 return null; } // 开始数据库查询 Object article = smsCouponDao.queryById(articleId); if (article != null) { // 数据不为空,放入缓存 redisTemplate.opsForValue().set(cacheKey, article, 60, TimeUnit.MINUTES); } else { // 数据为空,设置默认值,放入换存,设置较短的时间 redisTemplate.opsForValue().set(cacheKey, null, 5, TimeUnit.MINUTES); } } finally { // 解锁 redisLock.unlock(cacheKey, articleId); } return article; }
缓存雪崩
问题描述
缓存雪崩是指缓存不可用或者大量缓存由于超时时间相同在同一时间段失效,大量请求直接访问数据库,数据库压力过大导致系统雪崩。
解决方案
- 事前:redis 高可用,主从+哨兵,redis cluster,避免全盘崩溃。
- 事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死。
- 事后:redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。
优化建议
-
建议尽可能分散缓存过期时间,热门缓存时间长一些,冷门缓存时间短一些,也能节省缓存服务的资源。
-
存的过期时间可以取个随机值。这么做是为避免缓存同时失效。
转载地址:https://blog.csdn.net/qq_39739458/article/details/108261909 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年03月29日 13时12分39秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
嵌入式如何入门,要不要学习Python
2021-06-30
Linux 资料大全
2021-06-30
一个深入学习Linux/C/C++的原创技术号
2021-06-30
Linux 用户空间和内核空间
2021-06-30
深入理解cache对写好代码至关重要
2021-06-30
你确定你会使用git commit?
2021-06-30
你会选择深圳还是佛山?
2019-04-27
华为开始对嵌入式开发者下手了!
2019-04-27
生命很短,我用tldr
2019-04-27
FUSE文件系统
2019-04-27
可怕,别人把我MCU固件给反汇编了!
2019-04-27
Modbus协议概念最详细介绍
2019-04-27
在家工作多年再回深圳找工作,会不会丢脸?
2019-04-27
Linux内存寻址方式
2019-04-27
Linux 内核如何描述一个进程?
2019-04-27
FreeRTOS及其应用,万字长文,基础入门
2019-04-27
物联网开发者被疯抢,华为做了什么?
2019-04-27
从中工毕业到年薪30万,我用了2年9个月
2019-04-27
recovery模式下支持ADB连接和串口操作
2019-04-27