Redis缓存雪崩、穿透、击穿

2020-10-19  本文已影响0人  徒手說梦话

在双十一、618的节日中,会出现大量的用户请求下单,这对于数据库来说是一种特别大的压力,甚至可能会导致服务器宕机,这时候我们可以使用redis缓存在我们mysql前面拦截一部分请求,来减少我们数据库的压力,但是也会存在三种情况:Redis缓存雪崩、穿透、击穿

缓存雪崩

image-20201011171513209.png
双十一期间,所有用户一打开淘宝就是进入首页,首页的压力非常大,为了提高并发,将网站首页数据都缓存到redis里,所有的redis key失效时间都是3小时。

此时如果redis中key正好三个小时过去了,那么redis的key全部都失效,此时redis数据为空,数据只能打到数据库中,此时数据库会因为请求量过大导致宕机。

总结:在高并发下,大量缓存key在同一时间失效,大量请求直接落在数据库上,导致数据库宕机。

解决方案

缓存穿透

image-20201011174102454.png

某人恶意使用脚本疯狂的给网站发送请求,查询 id = -1 的数据,redis并没有这样的数据,这时候就穿透redis,直接打到了数据库上,结果把数据库搞挂了,然后网站也挂了。

总结

redis缓存和数据库中没有相关数据(例用户直接携带id<=0的参数不断发起请求),redis中没有这样的数据,无法进行拦截,直接被穿透到数据库,导致数据库压力过大宕机。

解决方案

缓存击穿

image-20201011221551513.png

双十一马爸爸突发奇想,想拍卖自己穿了20年的老布鞋,并且附带本人签名,程序员将该鞋的信息存到了redis中,设置了3小时过期。寻思3小时够他们抢了吧,但他低估了马爸爸的魅力。

该商品引起了一千万人关注,这些人不断的竞拍这双鞋,价格越拍越高,马爸爸乐开了花。

竞拍了2小时59分,马上要拍到一个亿了,突然这双鞋在redis里的key数据过期了,导致该key的大量请求,都打到了数据库,直接导致数据库挂掉了,服务无法响应。

总结

某一个热点key,在不停地扛着高并发,当这个热点key在失效的一瞬间,持续的高并发访问就击破缓存直接访问数据库,导致数据库宕机。

解决方案

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

总结

上一篇 下一篇

猜你喜欢

热点阅读