缓存雪崩、缓存穿透、缓存击穿

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Michaeles/article/details/85331365

一、缓存击穿(针对某一key缓存)

1.概念

针对于一些设置了过期时间的key,当缓存key在某个时间点过期,恰好此时有大量的并发请求进来,发现缓存过期时,就会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。

2.使用互斥锁(mutex key)

简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db。比如Redis使用SETNX去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。

public String get(key) {
      String value = redis.get(key);
      if (value == null) { //代表缓存值过期
          //设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
		  if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //代表设置成功
                      value = db.get(key);
                      redis.set(key, value, expire_secs);
                      redis.del(key_mutex);
              } else { 
          //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
                      sleep(50);
                      get(key);  //重试
              }
          } else {
              return value;      
          }
 }

3.提前"使用互斥锁(mutex key)

当从cache读取到timeout1发现它已经过期时候,马上延长timeout1并重新设置到cache。

4.永远不过期

(1)可以把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建。唯一不足的就是构建缓存时候,其余线程(非构建缓存的线程)可能访问的是老数据。

5. 使用netflix的hystrix进行资源保护

如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败,这个就是Hystrix需要做的事情。Hystrix提供了熔断、隔离、Fallback、cache、监控等功能,能够在一个、或多个依赖同时出现问题时保证系统依然可用。

二、缓存雪崩(针对很多key)

1.设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。

2.解决方案

(1)将缓存时间分散开,比如在原有失效时间的基础上增加一个随机值,降低同时失效的重复率。

(2)事前:redis高可用,主从+哨兵,redis cluster,避免全盘崩溃

         事中:本地ehcache缓存 + hystrix限流&降级,避免MySQL被打死

         事后:redis持久化,快速恢复缓存数据

三、缓存穿透

1.缓存穿透是指查询一个一定不存在的数据,如果存储层查不到数据就不写入缓存,就会向DB请求,流量大时就容易挂掉。利用不存在的key频繁攻击我们的应用,这就是漏洞。

2.解决方案

(1)采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉;

(2)查询不到的数据也放到缓存,value为空,如set -999 “”,但它的过期时间会很短,最长不超过五分钟。

猜你喜欢

转载自blog.csdn.net/Michaeles/article/details/85331365