Redis的缓存穿透、缓存击穿、缓存雪崩

Redis的缓存穿透、缓存击穿、缓存雪崩

在我们在查询数据时,在没有使用类似redis缓存的情况下,一般都是直接去数据库中查询,但是直接查询数据库的效率比使用redis缓存来查询数据的效率要低,所以我们需要增加缓存,但是使用redis缓存就存在一些问题,这里是对使用redis缓存的三类问题的总结。

1、缓存穿透

缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。

解决方法:

  • 缓存空对象

    当我们客户端访问不存在的数据时,先请求redis,但是此时redis中没有数据,此时会访问到数据库,但是数据库中也没有数据,这个数据穿透了缓存,直击数据库,我们都知道数据库能够承载的并发不如redis这么高,如果大量的请求同时过来访问这种不存在的数据,这些请求就都会访问到数据库。为防止这个问题的发生,对于访问的这个数据在数据库中即使不存在,我们也把这个数据存入到redis中去,这样,下次用户过来访问这个不存在的数据,那么在redis中也能找到这个数据。

    public void set(String key, Object value, Long time, TimeUnit unit){
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value),time,unit);
    }
    
    =========================================================================================================
    
    public <R,ID> R queryWithPassThrough(String keyPrefix,ID id,Class<R> type,Function<ID,R> dbFallback,Long time,TimeUnit unit){
        //1.从redis查询缓存
        String json = stringRedisTemplate.opsForValue().get(keyPrefix + id);
        //2.判断是否存在
        if(StrUtil.isNotBlank(json)){
            //3.存在,直接返回
            return  JSONUtil.toBean(json, type);
        }
        //判断命中的是否为空值
        if(json!=null){
            //这个是用来反馈信息的
            return null;
        }
        //4.不存在,根据id查询数据库
        //交给调用者
        R r = dbFallback.apply(id);
        //5.不存在返回错误
        if(r==null){
            //空值写入redis
            stringRedisTemplate.opsForValue().set(keyPrefix+id,"",time,unit);
            return null;
        }
        //6.存在写入redis
       this.set(keyPrefix+id,r,time,unit);
        //7.返回
        return r;
    }
    
  • 布隆过滤器

    布隆过滤器其实采用的是哈希思想来解决这个问题,通过一个庞大的二进制数组,走哈希思想去判断当前这个要查询的这个数据是否存在,如果布隆过滤器判断存在,则放行,这个请求会去访问redis,哪怕此时redis中的数据过期了,但是数据库中一定存在这个数据,在数据库中查询出来这个数据后,再将其放入到redis中,

    假设布隆过滤器判断这个数据不存在,则直接返回

    这种方式优点在于节约内存空间,存在误判,误判原因在于:布隆过滤器走的是哈希思想,只要哈希思想,就可能存在哈希冲

    优缺点

    • 优点

      节省大量的内存空间、时间复杂度,节省内存空间是因为一个二进制向量。时间复杂度是根据映射函数查询,假设有K个映射函数,那么时间复杂度就是O(K)。

    比较安全,因为存的不是元素本身,而是二进制向量

    • 缺点

      存在一定的误判。

      不能删除布隆过滤器里的元素。

2、缓存雪崩

缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。

解决方法:在过期时间上增加⼀点随机值,另外如果搭建⼀个⾼可⽤的Redis集群也是防⽌缓 存雪崩的有效⼿段

3、缓存击穿

缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。

解决方法:

  1. 考虑这个热点key不设过期时间

  2. 使用互斥锁

    因为锁能实现互斥性。假设线程过来,只能一个人一个人的来访问数据库,从而避免对于数据库访问压力过大,但这也会影响查询的性能,因为此时会让查询的性能从并行变成了串行。对于锁的实现可以通过redis中的setnx来实现。

    当第一个人访问时,缓存并未命中,第一个人就需要拿到锁并从数据库中取出数据在redis中重新缓存数据,在第一个没有释放锁时,其他人的访问请求只能等待,直到第一个人释放锁后,在redis中可以查询到数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值