缓存雪崩 缓存击穿 缓存雪崩出现原因及解决方案

缓存雪崩

大量的应用请求无法在Redis缓存中进行处理,紧接着应用将大量请求发送到数据库层,导致数据库层的压力激增

缓存雪崩一般有两个原因导致,解决方案也有所不同

出现原因一

缓存中有大量Key同时过期,导致大量请求无法得到处理,大量数据需要回源数据库

解决方案
方案一 差异化设置过期时间

差异化缓存过期时间,不要让大量的 Key 在同一时间过期。比如,在初始化缓存的时候,给这些数据的过期时间增加一个较小的随机数,这样一来不同数据的过期时间有所差别又差别不大,即避免了大量数据同时过期又能保证这些数据在相近的时间失效

方案二 服务降级

允许核心业务访问数据库,非核心业务直接返回预定义的信息

方案三 不设置过期时间

初始化缓存数据的时候设置缓存永不过期,然后启动一个后台线程 30 秒一次定时把所有数据更新到缓存,而且通过适当的休眠,控制从数据库更新数据的频率,降低数据库压力。

出现原因二

Redis实例发生故障宕机,无法处理请求,就会导致大量请求积压到数据库层

解决方案
方案一 服务熔断

暂停业务应用对缓存服务的访问,从而降低对数据库的压力

方案二 请求限流

控制每秒进入应用程序的请求数,避免过多的请求被发到数据库

方案三 Redis构建高可靠集群

通过主从节点的方式构建Redis高可靠集群。可以保证在Redis主节点故障宕机时,从节点切换到主节点,继续提供服务,避免由于缓存实例宕机导致缓存雪崩

缓存击穿

热点数据在某一时刻过期了,可能会导致随之而来的大量的并发请求直接打到数据库,导致数据库压力激增。

解决方案
方案一 分布式锁

采用锁机制控制打到数据库的请求,读取数据后将其写回到缓存,保证了其他线程可以命中缓存。

//伪代码
加锁成功;
result=redis.getKey(X);
if(result==null){
  result=db.getData(X);
  redis.setData(X,result);
}
释放锁;
方案二 热点数据不设置过期时间

缓存穿透

客户端 请求了一个业务程序中不存在的数据,即要访问的数据既不在Redis缓存中,也不在数据库中。导致每次类似的请求,都会先从Redis–>数据库去查数据,最终也无果。

当存在大量请求这样访问时,会同时给缓存和数据库带来很大压力。

出现原因

1、误操作导致:缓存中的数据和数据库中的数据都被误删了

2、恶意攻击:专门访问数据库中不存在的数据

解决方案
方案一 设置缺省值

比如当请求id=1000的用户数据时,在数据库中找不到该条数据,则将NONE这样具有特殊含义的字符串设置到缓存中,后续客户端再请求该数据时,可以直接命中缓存,不再访问数据库。

但是这样有个问题,如果客户端访问大量的不同的数据,那这些大量无效的数据可能会占满缓存

方案二 使用布隆过滤器过滤数据

布隆过滤器由一个初值都为 0 的 bit 数组和 N 个哈希函数组成,可以用来快速判断某个数据是否存在。

工作原理

1、使用 N 个哈希函数,分别计算这个数据的哈希值,得到 N 个哈希值

2、把这 N 个哈希值对 bit 数组的长度取模,得到每个哈希值在数组中的对应位置。

3、标记数据,把对应位置的 bit 位设置为 1

如果数据不存在,那布隆过滤器中bit数组对应的bit位的值为0.

过滤规则

当一个元素需要被检索时,使用N个哈希函数对该元素求得哈希值,并定位到bit数组中。如果发现对应位置处bit位有任何一个0,就说明这个元素不存在于布隆过滤器;当bit位都是1,说明这个元素可能存在于布隆过滤器(这里说可能,是因为不同元素经过哈希运算可能得到相同的哈希值)

像Guava、Redisson 都有布隆过滤器的实现。

我们只需要初始化布隆过滤器,即将数据添加到布隆过滤器中。然后借助布隆过滤器去判断元素是否存在

参考文献
Redis核心技术与实战

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值