redis缓存穿透,缓存击穿,缓存雪崩

缓存击穿

key对应的数据存在,但在redis中过期,此时若有大量并发请求过来查询同一个key,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。

解决方案

使用互斥锁(mutex key)

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

SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。

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

缓存穿透

大量查询不存在的数据,从而跳过缓存直接查询数据,造成数据库崩溃。
由于不恰当的业务功能实现,或者外部恶意攻击不断地请求某些不存在的数据内存, 由于缓存中没有保存该数据,导致所有的请求都会落到数据库上,对数据库可能带 来一定的压力,甚至崩溃。

解决方案

  1. 针对缓存穿透的情况, 简单的对策就是将不存在的数据访问结果, 也存储到缓存中并设置过期时间,避免缓存访问的穿透。最终不存在商品数据的访问结果也缓存下来。有效的避 免缓存穿透的风险。
  2. 布隆过滤器:将数据库中所有的查询条件,放入布隆过滤器中,当一个查询请求过来时,先经过布隆过滤器进行查,如果判断请求查询值存在,则继续查;如果判断请求查询不存在,直接丢弃。

缓存雪崩

当缓存重启或者大量的缓存在某一时间段失效, 这样就导致大批流量直接访问数据 库, 对 DB 造成压力, 从而引起 DB 故障,系统崩溃。 举例来说,我们在准备一项抢购的促销运营活动,活动期间将带来大量的商品信息、 库存等相关信息的查询。为了避免商品数据库的压力,将商品数据放入缓存中存储。 不巧的是,抢购活动期间,大量的热门商品缓存同时失效过期了,导致很大的查询 流量落到了数据库之上。对于数据库来说造成很大的压力。

解决方案

	1. 将商品根据品类热度分类, 购买比较多的类目商品缓存周期长一些, 购买 相对冷门的类目商品,缓存周期短一些; 
	2. 在设置商品具体的缓存生效时间的时候, 加上一个随机的区间因子, 比如 说 5~10 分钟之间来随意选择失效时间; (最优选择)
	3. 提前预估 DB 能力, 如果缓存挂掉,数据库仍可以在一定程度上抗住流量 的压力 这三个策略能够有效的避免短时间内,大批量的缓存失效的问题。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值