前面讲过一些redis 缓存的使用和数据持久化。感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhong/category/771056.html 。今天总结总结缓存使用过程中遇到的一些常见的问题。比如缓存雪崩,缓存穿透,缓存预热等等。

缓存雪崩

  缓存雪崩是由于原有缓存失效(过期),新缓存未到期间。所有请求都去查询数据库,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。

  1. 碰到这种情况,一般并发量不是特别多的时候,使用最多的解决方案是加锁排队。

        public object GetProductListNew(){const int cacheTime = 30;const string cacheKey = "product_list";const string lockKey = cacheKey;var cacheValue = CacheHelper.Get(cacheKey);if (cacheValue != null){return cacheValue;}else{lock (lockKey){cacheValue = CacheHelper.Get(cacheKey);if (cacheValue != null){return cacheValue;}else{cacheValue = GetProductListFromDB(); //这里一般是 sql查询数据。
                        CacheHelper.Add(cacheKey, cacheValue, cacheTime);}                    }return cacheValue;}}    

  2. 加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量。假设在高并发下,缓存重建期间key是锁着的,这是过来1000个请求999个都在阻塞的。同样会导致用户等待超时,这是个治标不治本的方法。

  还有一个解决办法解决方案是:给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存。

     public object GetProductListNew(){const int cacheTime = 30;const string cacheKey = "product_list";//缓存标记。const string cacheSign = cacheKey + "_sign";var sign = CacheHelper.Get(cacheSign);//获取缓存值var cacheValue = CacheHelper.Get(cacheKey);if (sign != null){return cacheValue; //未过期,直接返回。
            }else{CacheHelper.Add(cacheSign, "1", cacheTime);ThreadPool.QueueUserWorkItem((arg) =>{cacheValue = GetProductListFromDB(); //这里一般是 sql查询数据。CacheHelper.Add(cacheKey, cacheValue, cacheTime*2); //日期设缓存时间的2倍,用于脏读。
                });return cacheValue;}} 

  缓存标记:记录缓存数据是否过期,如果过期会触发通知另外的线程在后台去更新实际key的缓存。

  缓存数据:它的过期时间比缓存标记的时间延长1倍,例:标记缓存时间30分钟,数据缓存设置为60分钟。 这样,当缓存标记key过期后,实际缓存还能把旧数据返回给调用端,直到另外的线程在后台更新完成后,才会返回新缓存。

  这样做后,就可以一定程度上提高系统吞吐量。

缓存穿透

  缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。

  解决的办法就是:如果查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库,这种办法最简单粗暴。

        public object GetProductListNew(){const int cacheTime = 30;const string cacheKey = "product_list";var cacheValue = CacheHelper.Get(cacheKey);if (cacheValue != null)return cacheValue;cacheValue = CacheHelper.Get(cacheKey);if (cacheValue != null){return cacheValue;}else{cacheValue = GetProductListFromDB(); //数据库查询不到,为空。if (cacheValue == null){cacheValue = string.Empty; //如果发现为空,设置个默认值,也缓存起来。
                }CacheHelper.Add(cacheKey, cacheValue, cacheTime);return cacheValue;}}    

  把空结果,也给缓存起来,这样下次同样的请求就可以直接返回空了,即可以避免当查询的值为空时引起的缓存穿透。同时也可以单独设置个缓存区域存储空值,对要查询的key进行预先校验,然后再放行给后面的正常缓存处理逻辑。

缓存预热

  缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样避免,用户请求的时候,再去加载相关的数据。

  解决思路:

    1,直接写个缓存刷新页面,上线时手工操作下。

    2,数据量不大,可以在WEB系统启动的时候加载。

    3,定时刷新缓存,

缓存更新

  缓存淘汰的策略有两种:

    (1) 定时去清理过期的缓存。

    (2)当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。

  两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂,具体用哪种方案,大家可以根据自己的应用场景来权衡。1. 预估失效时间 2. 版本号(必须单调递增,时间戳是最好的选择)3. 提供手动清理缓存的接口。

  我前面有篇文章,是介绍缓存系统的缓存更新的。感兴趣的朋友可以看看:http://www.cnblogs.com/zhangweizhong/p/5884761.html

总结

  这些都是实际项目中,可能碰到的一些问题。实际上还有很多很多各种各样的问题。缓存层框架的封装往往要复杂的多。应用场景不同,方法和解决方案也不同。具体要根据实际情况来取舍。

转载于:https://www.cnblogs.com/zhangweizhong/p/6258797.html

Redis总结(五)缓存雪崩和缓存穿透等问题相关推荐

  1. Redis缓存雪崩、缓存穿透、热点Key解决方案和分析

    转载自  https://blog.csdn.net/wang0112233/article/details/79558612 https://www.sohu.com/a/230787856_231 ...

  2. redis缓存穿透、缓存雪崩、缓存击穿、并发竞争

    关注微信公众号"虾米聊吧",每天更新一篇技术文章,文章内容涵盖架构师成长必经之路应掌握的技术,一起学习,一起交流. 缓存穿透.缓存雪崩.缓存击穿.并发竞争是缓存最常见的几个问题,接 ...

  3. Redis系列教程(三):如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题

    Java相关的面试都会问到缓存的问题:史上最全Redis面试49题(含答案):哨兵+复制+事务+集群+持久化等,除此之外还会问到缓存雪崩.缓存穿透.缓存预热.缓存更新.缓存降级等不常见的问题,但却是非 ...

  4. 【重难点】【Redis 03】缓存雪崩、缓存穿透、缓存击穿、Redis 的内存过期策略、并发读写和双写

    [重难点][Redis 03]缓存雪崩.缓存穿透.缓存击穿.Redis 的内存过期策略.并发读写和双写 文章目录 [重难点][Redis 03]缓存雪崩.缓存穿透.缓存击穿.Redis 的内存过期策略 ...

  5. 大厂面试Redis:缓存雪崩、缓存穿透、缓存击穿

    欢迎关注这个有趣的灵魂 眼光不错,小伙子,看到这篇文章了就血赚,这篇文章绝对让你学到开心,这是面试的杀器,其实Redis这个东西吧,我个人认为,真的真的很强大,但是呢,又感觉被吹得有点过头了 不过人家 ...

  6. Redis系列:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级

    今天给大家整理一篇关于Redis经常被问到的问题:缓存雪崩.缓存穿透.缓存预热.缓存更新.缓存降级等概念 一.缓存雪崩 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓 ...

  7. Redis专题-缓存穿透、缓存雪崩、缓存击穿

    一.缓存穿透 缓存穿透概念 缓存穿透是指查询一个一定不存在的数据,在数据库没有,自然在缓存中也不会有.导致用户查询的时候,在缓存中找不到对应key的value,每次都要去数据库再查询一遍,如果从存储层 ...

  8. Redis 的缓存异常处理 —— 缓存雪崩、缓存击穿、缓存穿透

    Redis 的缓存异常处理 -- 缓存雪崩.缓存击穿.缓存穿透 在实际应用 Redis 过程中,如果将 Redis 作为数据库的缓存,经常会遇到这几个问题:缓存雪崩.缓存击穿.缓存穿透等. 缓存雪崩 ...

  9. Redis缓存雪崩、缓存穿透、热点Key

    我们通常使用 缓存 + 过期时间的策略来帮助我们加速接口的访问速度,减少了后端负载,同时保证功能的更新. 1.缓存穿透 缓存系统,按照KEY去查询VALUE,当KEY对应的VALUE一定不存在的时候并 ...

最新文章

  1. html二级下拉导航,html -----二级下拉导航的实现(常用)
  2. Windows中现在有独立的Linux文件夹系统
  3. P2689 东南西北
  4. 二分查找算法的两种实现方式:非递归实现和递归实现
  5. Toast源码深度分析
  6. Thymeleaf 简介、教程
  7. 懒人专用SSH框架下的基本配置
  8. 第九:Pytest进阶之xunit fixture
  9. Facebook 发币 Libra;谷歌十亿美金为穷人造房;第四代树莓派 Raspberry Pi 4 发布 | 开发者周刊...
  10. ExtJS学习之EditorGridPanel
  11. 反向题在测试问卷信效度_调查问卷的信效度分析
  12. 50年的追踪拍摄:社会阶级能被逾越吗?
  13. 事件循环、webpack、vue<前端学习笔记>
  14. 云计算如何与企业管理协同作战
  15. 合并拆分wim文件命令imagex
  16. 法国物联网公司Sigfox 获1.6亿美元E轮融资
  17. 解决:ActiveX控件不能使用
  18. cocos creator运行正常,微信开发者工具中报错XXX is not defined.
  19. Vue之 解决下拉框默认选中的是数字key 不是汉字value值
  20. 无域控AlwaysOn实战教学 (一)

热门文章

  1. linux学习笔记(软件包管理)
  2. 使PropertyGrid控件的属性值可以显示多行的方法
  3. JS放在博客里面运行
  4. 【原创·教程·连载】Microsoft SQL Server 2008 Reporting Services应用系列(一)安装篇...
  5. Eclipse插件开发中File和IFile的转换
  6. [RN] React Native 自定义 底部 弹出 选择框 实现
  7. react部署之页面空白
  8. javascript 点点滴滴 jquery
  9. bzoj2243 [SDOI2011]染色
  10. 物联网产业链及市场分