一文搞懂Redis缓存穿透/击穿/雪崩

缓存穿透

问题描述
缓存穿透是指查询一个一定不存在的数据,由于缓存时不命中的,则需要从数据库中查询。查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库中去查询,进而增大了数据库的压力。如不断发起“id=-1”等不可能存在的数据的请求,此时缓存中没有就会向DB读取进而可能导致DB挂掉。

解决方案
1、增加接口层校验
2、每次查询数据库不存在的数据时缓存一个空对象,并设置过期时间(解决单个不存在的key多次查询,造成内存空间浪费)
3、使用布隆过滤器(注意:必须将所有的key都放到布隆过滤器和redis里,否则请求会被直接返回空数据)

缓存击穿

问题描述
对于设置了过期时间的key,缓存在某个时间点过期的时候,恰好这个时间点对这个key有大量的并发请求过来,这些请求发现缓存过期一般会从数据库中进行查询并添加到缓存中,这个时候突然大的并发进来会把数据库压垮。

解决方案
1、使用互斥锁:当缓存失效时,不立即去查询数据库,先使用例如redis的setnx命令去设置一个互斥锁,当操作成功返回时在进行load db并将查询的数据添加到缓存当中,否则重试获取缓存的方法,具体逻辑代码如下

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;        
          }  
 } 

2、设置热点数据永不过期

缓存雪崩

问题描述
设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部打到数据库,数据库瞬间压力过重雪崩,与缓存击穿的区别是:雪崩是很多key过期,而击穿是单个key

解决方案
1、将缓存的过期时间分散开(在原有失效的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,很难引起key集体失效的情况)
2、缓存永不过期(空间换效率)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值