Redis缓存的雪崩,穿透,击穿总结

  • 缓存在大并发系统中的重要性作用不言而喻。缓存属于内存操作,微秒或毫秒级别。在互联网公司绝对绕不过这个缓存。缓存有很多mc,redis等。这里描述的是redis.因为redis可以持久化,而mc纯内存,重启机器数据就无法找回。redis则还可以重新从磁盘中导入数据。缓存则又有绕不开的问题。那就是雪崩,击穿,穿透问题。

缓存雪崩:

    1. 现象:
      影响轻则,查询变慢,当请求并发更高时,则出来大面积服务不可用。
    1. 原因:
      同一时间缓存大面积失效,就像没有缓存一样,所有的请求直接打到数据库上来,DB扛不住挂了,如果是重要的库,例如用户库,那牵联就一大片了,瞬间倒一片。
    1. 案例:
      电商首页缓存,如果首页的key全部都在某一时刻失效,刚好在那一时刻有秒杀活动,那这样的话就所有的请求都被打到了DB。并发大的情况下DB必然扛不住,没有其他降级之类的方案的话,DBA也只能重启DB,但是这样又会被新的流量搞挂。
    1. 解决方案:
      批量往redis存数据的时候,把每个key的失效时间加上个随机数,这样的话就能保证数据不会在同一个时间大面积失效。

缓存穿透:

    1. 现象与原因:
      就是指用户不断发起请求的数据,在缓存和DB中都没有,比较DB中的用户ID是自增的,但是用户请求传了-1,或者是一个特别大的数字,这个时候用户很有可能就是一个攻击者,这样的功击会导致DB的压力过大,严重的话就是把DB搞挂了。因为每次都绕开了缓存直接查询DB
    1. 解决方案:
    • 方法一:在接口层增加校验,不合法的参数直接返回。不相信任务调用方,根据自己提供的API接口规范来,作为被调用方,要考虑可能任何的参数传值。
    • 方法二:在缓存查不到,DB中也没有的情况,可以将对应的key的value写为null,或者其他特殊值写入缓存,同时将过期失效时间设置短一点,以免影响正常情况。这样是可以防止反复用同一个ID来暴力攻击。
    • 方法三:正常用户是不会这样暴力功击,只有是恶意者才会这样做,可以在网关NG作一个配置项,为每一个IP设置访问阀值。
    • 方法四:高级用户布隆过滤器(Bloom Filter),这个也能很好地防止缓存穿透。原理就是利用高效的数据结构和算法快速判断出你这个Key是否在DB中存在,不存在你return就好了,存在你就去查了DB刷新KV再return。

缓存击穿:

    1. 现象与原因:
      跟缓存雪崩类似,但是又有点不一样。雪崩是因为大面积缓存失效,请求全打到DB;而缓存击穿是指一个key是热点,不停地扛住大并发请求,全都集中访问此key,而当此key过期瞬间,持续的大并发就击穿缓存,全都打在DB上。就又引发雪崩的问题。
    1. 解决方案:
      设置热点key不过期。或者加上互斥锁。

总结:

这就是三者的区别,差不多,但又有一些区别。因为缓存雪崩、穿透和击穿,是缓存最大的问题,要么不出现,一旦出现就是致命性的问题
一般避免以上情况发生我们从三个时间段去分析下:

  • 事前:Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃。
  • 事中:本地 ehcache 缓存 + Hystrix 限流+降级,避免** MySQL** 被打死。
  • 事后:Redis 持久化 RDB+AOF,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。

扩展知识:

可以用限流组件,设置每秒的请求,有多少能通过组件,剩余的未通过的请求,怎么办?走降级!可以返回一些默认的值,或者友情提示,或者空白的值。
这样的好处就是:数据库绝对不会死,限流组件确保了每秒只有多少个请求能通过。 只要数据库不死,就是说,对用户来说,3/5 的请求都是可以被处理的。 只要有 3/5 的请求可以被处理,就意味着你的系统没死,对用户来说,可能就是点击几次刷不出来页面,但是多点几次,就可以刷出来一次。
摘抄自网络

猜你喜欢

转载自juejin.im/post/5dc416866fb9a04a972e6e3d