Redis缓存穿透、缓存雪崩、缓存击穿及解决方案

通过redis构建缓存时,会出现如下几个问题:
缓存穿透
缓存穿透是指查询一个根本不存在的数据(缓存和数据库都没有),先查缓存,缓存没有,再去数据库中拿,而数据库中也没有,这样的请求如果不停地接收,那系统存储层会造成巨大压力,失去了缓存保护后端存储的意义。
出现缓存穿透的基本原因可能是自身业务代码或者数据出现问题,以及一些恶意攻击
问题解决
1.缓存空对象

伪代码
取数据时先查找缓存,有则返回,无则取数据库
String get(String key){
  //从缓存中取数据
  String cacheV = cache.get(key);
 //缓存为空
 if(stringUtils.isBlank(cacheV)){
         //从数据库中取,放入缓存
          String dbV = db.get(key);
          cache.set(key,dbV);
          //数据库是null ,设置过期时间
          if(dbV == null){
             cache.expire(key,60*6);
          }
        return dbV; 
 }else{
          return cacheV; 
 }
}

2.布隆过滤器
关于布隆过滤器我在上篇文章中说到了,它能过滤一定不存在,因为有hash冲突,如果一个key通过几次hash运算刚好对应的位值为1,则判断为存在,所以它的存在指的是可能存在,这种概率极低。

//初始化布隆过滤器
RBloomFilter<String> bloomFilter = redisson.getBloomFilter("names");
//初始化布隆过滤器:预计元素为100000000L,误差率为3%
bloomFilter.tryInit(100000000L,0.03); 
//把所有数据存入布隆过滤器
void init(){
    for (String key: keys) {
        bloomFilter.put(key);
    }
}

String get(String key) {
    // 从布隆过滤器这一级缓存判断下key是否存在
    Boolean exist = bloomFilter.contains(key);
    if(!exist){
        return "";
    }
    // 从缓存中获取数据
    String cacheV = cache.get(key);
    // 缓存为空
    if (stringUtils.isBlank(cacheV)) {
        // 从存储中获取
        String dbV = db.get(key);
        cache.set(key, dbV);
        // 这里就是解决刚才说的那种极低事件的发生
        if (dbV == null) {
            cache.expire(key, 60 * 6);
        }
        return dbV;
    } else {
        // 缓存非空
        return cacheV;
    }
}

缓存击穿
缓存击穿指的是少量的热点key在不停的被访问,这是突然失效了,大量请求到数据库层,就像是在缓存层有了一个洞。
解决方案: 设置热点key 永不过期,或者使用互斥锁、分布式锁重建缓存

String get(String key){
  //从缓存中取数据
  String cacheV = cache.get(key);
 //缓存为空
  if(stringUtils.isBlank(cacheV)){
        //让第一个请求进来
     String mutexKey = "m:key:" + key;
        if (redis.set(mutexKey, "2", "ex 180", "nx")) {
             // 从数据源获取数据
            value = db.get(key);
            // 回写Redis, 并设置过期时间
            redis.setex(key, timeout, value);
            // 删除key_mutex
            redis.delete(mutexKey);
        }
        else {// 其他线程休息500毫秒后重试
            Thread.sleep(500);
            get(key);
        }
 }
         return cacheV; 
}

缓存雪崩
缓存雪崩指缓存层支撑不起大量的流量导致宕机了,造成缓存层无效,崩塌,流量打到数据库。
解决方案:
保证缓存层的高可用性,比如redis 哨兵或集群模式。
使用上面的方式进行热点数据缓存重建,或热点数据随机过期。
使用降级熔断组件。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值