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


 缓存与数据库的双写一致性问题回顾

应用程序写数据时:

先写缓存,成功后再写数据库;[写-写]

先写数据库,成功后再写缓存;[写-写]

以上两种方案,存在双写不一致的问题。

在写数据时,可能存在缓存写成功,数据库写失败;或者数据库写成功,缓存写失败。从而造成数据不一致。当多个请求发生时,也可能产生读写冲突的并发问题。

缓存的最佳策略是:

数据操作的基本步骤

1. 根据key读缓存;

2. 命中则直接返回;

3. 若key不在缓存中,则根据key读数据库;

4. 读取成功后,更新缓存中的key值

数据操作的基本步骤

1. 根据key写数据库;

2. 写数据库成功后,删除缓存;

为了尽可能保证缓存与数据库的一致性,可以采用延时双删

为了防止缓存删除失败,采用异步重试机制,利用canal订阅mysql的binlog日志监听消息队列,重试删除操作。

图片


 缓存穿透

缓存穿透:查询的数据在缓存和数据库中都不存在,由于缓存未命中,导致每次请求该数据都要去数据库再查询一遍。

造成缓存穿透的情况有两种:

(1) 用户请求的key值在系统中不存在时,会查询数据库,造成数据库服务器的压力。

(2) 利用不存在的key频繁攻击系统,在短时间内有大量系统不存在的随机key发起了查询请求,而这些不存在的key在缓存里找不到,引发了大量对数据库服务器的查询请求,从而导致了数据库服务器的宕机。

图片

穿透的解决方案

1. 设置空值

当在数据库中也未查询到该key时,在缓存中为key设置空值,防止对数据库发起重复查询。设置空值方案存在问题:不在系统中的key值是无限的,如果均设置key值为空,会造成内存资源的极大浪费,引起性能急剧下降。

2. 布隆过滤器

使用布隆过滤器来过滤掉系统中不存在的key,从而避免请求穿透缓存去查询数据库。

实现方式:在缓存之前添加一个布隆过滤器,将系统中所有可能存在的key全部映射到布隆过滤器中。当查询请求到来的时候,先到布隆过滤器里面对key进行过滤,只允许系统中存在的key进行后续查询。

图片

「布隆过滤器」是一个很长的二进制向量和一系列随机映射函数,用于快速判断元素是否存在于集合中。

布隆过滤器的原理:

1. 布隆过滤器使用一个位数组(Bit Array),初始时所有的位都设置为0。

2. 当向布隆过滤器中添加元素时,使用多个哈希函数将元素映射到位数组中的几个位置,把这几个位置的值设置为1。

3. 当要判断一个元素是否属于集合时,使用这些哈希函数将元素映射到位数组中的几个位置,并检查对应位置的值是否为1。如果对应的位置都为1,则说明元素可能属于集合;如果任意一个位置的值为0,则说明元素一定不属于集合。

图片

布隆过滤器的优点:

1. 占用内存小。

2. 查询效率高。

3. 不需要存储元素本身。

布隆过滤器的缺点:

1. 有一定的误判率。

2. 不能获取元素本身。

3. 一般情况下不能从布隆过滤器中删除元素。


 缓存击穿

缓存击穿:某个超热点数据的缓存突然失效,导致大量请求直接访问数据库,数据库压力瞬间升高,同时引起大量的缓存更新操作,造成整个系统性能急剧下降。

击穿的解决方案

1. 缓存失效后,通过加锁队列的方式控制写缓存的线程数量,保证缓存的单线程写,使得缓存更新串行化,大量的缓存更新操作排队进行,从而降低更新频率。

2. 缓存预热:系统上线后,提前加载热门数据到缓存中,避免在流量高峰期读数据库。

3. 限流策略:通过限制并发访问的请求数量,避免系统在缓存失效时被大量请求冲垮。

4. 热点数据永不过期:不给缓存设置过期时间,而是将过期时间存在key对应的value里,开启一个定时任务,定期查看缓存的过期时间,如果发现快要过期了,通过一个后台的异步线程去主动更新缓存。

图片


 缓存雪崩

缓存雪崩:由于缓存中大量的key设置了相同的过期时间,导致大规模的缓存在某一时刻同时失效,或者是缓存节点宕机,造成数据库请求瞬时爆量,系统崩溃。

雪崩的解决方案

1. 设置随机的缓存失效时间:给不同的key设置随机的失效时间,可以在原有的失效时间按上增加一个随机值,使失效时间的分布尽量均匀,从根源上避免大量缓存key值同时失效。

2. 设置两级或多级缓存:将缓存划分为多个层级,每个层级具有不同的过期时间和容量。

3. 限流:通过限制并发访问的请求数量,避免系统在缓存失效时被大量请求冲垮。

4. 熔断:在数据库访问出现故障时,通过切断对数据库的请求并提供备选方案来防止故障蔓延。

图片


 总结

穿透:查询的数据在缓存中不存在,数据库中也不存在。--- key不存在

击穿:热点数据的缓存突然失效。--- 热点的key失效

雪崩:大量的缓存在某一时刻同时失效。--- 大规模的key失效

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值