Redis之缓穿透

  缓存穿透:用户发起请求访问Redis缓存,缓存中没有数据然后去访问数据库,结果数据库也没有这个数据,也就是说请求最终都会到数据库,从而可能压垮数据库。例子:用一个数据库中ID不存在的用户一直不停的 发送请求,如果有网络黑客利用此漏洞进行攻击数据库可能就会直接崩掉;

解决方案

  • 布隆过滤器:将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力
  • 存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源;
      
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    //伪代码
    public object GetProductListNew() {
    int cacheTime = 30;
    String cacheKey = "product_list";
    //缓存标记
    String cacheSign = cacheKey + "_sign";
    String sign = CacheHelper.Get(cacheSign);
    //获取缓存值
    String cacheValue = CacheHelper.Get(cacheKey);
    if (sign != null) {
    return cacheValue; //未过期,直接返回
    } else {
    CacheHelper.Add(cacheSign, "1", cacheTime);
    ThreadPool.QueueUserWorkItem((arg) -> {
    //这里一般是 sql查询数据
    cacheValue = GetProductListFromDB();
    //日期设缓存时间的2倍,用于脏读
    CacheHelper.Add(cacheKey, cacheValue, cacheTime * 2);
    });
    return cacheValue;
    }
    }


### Redis之缓击穿

  缓存击穿:缓存在某个时间点突然过期,恰好这个时候并发很多,访问的都是这个Key,因为缓存中没有数据则去请求数据库,造成数据库压力过大可能崩掉;缓存击穿只是针对某一个Key的缓存;

解决方案

  • 数据预热
  • 加互斥锁
  • 数据永不过期


Redis之雪崩

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

解决方案

  • 缓存失效时的雪崩效应对底层系统的冲击非常可怕。大多数系统设计者考虑用加锁或者队列的方式保证缓存的单线 程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。这里分享一个简单方案就是将缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。
  • 数据永不过期