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

缓存处理流程

前台请求数据,先到缓存(Redis)中去取,如果有则直接返回数据;如果没有,则进一步到数据库中去获取数据。在高并发的场景之下,使用缓存可以快很多;但如果大量的请求越过缓存,请求数据库,那必然会给数据库带来很大的压力,会出现下面所说的缓存穿透、缓存击穿和缓存雪崩的问题。
在这里插入图片描述

缓存穿透

缓存穿透是指查询一个不存在的数据,由于缓存是不命中时被动写的。如果从数据库中查不到数据,则不会写入缓存,所以这将导致不存在的数据每次请求都要到DB中去查询,失去了缓存的意义。特别是在流量大的时候,可能数据库就挂掉了。

解决方法:

  1. 缓存空值,这样不会查询数据库;
  2. 采用布隆过滤器:将所有可能存在的数据哈希到一个足够大的 bitmap 中,如果查询不存在的数据,则会被这个 bitmap 拦截掉,从而避免了对数据库的查询压力。

布隆过滤器原理:当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把他们置成1.查询时,将元素通过散列函数映射后得到K个点,如果这些点在位图中有任意一个是0,则被检测元素不存在,直接拦截掉并返回;如果都是1,则查询元素可能存在,就会进一步查询Redis和数据库。

缓存雪崩

缓存雪崩是指我们在设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,此时请求全部转发给数据库,数据库瞬时压力过大挂掉。

解决方法:

  1. 过期时间打散:在原有的失效时间的基础上增加一个随机值,使得过期时间分散一点,不会在同一个时间失效;
  2. 设置热点数据不过期:热点数据不过期,就会减小发生雪崩的可能性;

缓存击穿

当大量的请求同时查询一个key的时候,此时正好这个key在缓存中失效了,就会导致大量的请求都落到数据库,致使数据库宕机。

解决方法:

  1. 设置热点数据不过期
  2. 加锁:第一个请求的线程可以拿到锁,拿到锁的线程查询到数据之后设置缓存,其他的线程获取锁失败后会等待50ms,然后重新到缓存中获取数据,这样就可以避免大量的请求落到数据库中。

加锁的代码思想如下:

public Object getData(String key) throws InterruptedException {
    Object value = redis.get(key);
    // 缓存值过期
    if (value == null) {
        // lockRedis:专门用于加锁的redis;
        // "empty":加锁的值随便设置都可以
        if (lockRedis.set(key, "empty", "PX", lockExpire, "NX")) {
            try {
                // 查询数据库,并写到缓存,让其他线程可以直接走缓存
                value = getDataFromDb(key);
                redis.set(key, value, "PX", expire);
            } catch (Exception e) {
                // 异常处理
            } finally {
                // 释放锁
                lockRedis.delete(key);
            }
        } else {
            // sleep50ms后,进行重试
            Thread.sleep(50);
            return getData(key);
        }
    }
    return value;
}

上述代码意味着:每个客户端线程请求key的数据,如果在redis中得到了对应的value,直接返回;如果value为空(即数据不在缓存中),则需要进一步查询数据库。此时想查询数据库的线程就要去争夺key的锁,第一个率先得到锁的就会在数据库中得到value并返回,并设置缓存;没有得到锁的则sleep 50ms,然后继续试图从缓存中得到key对应的值,往复循环,直到得到value。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值