Redis缓存穿透与雪崩

概述

在这里插入图片描述

缓存穿透(数据库查不到)

用户想要查询一个数据,发现redis中没有,也就是缓存每命中,于是向持久层数据库中查询,发现数据库中也没有,于是本次查询失败。当用户很多时候,缓存一直没有命中(比如秒杀场景),于是都去请求数据库了。这会给数据库造成很大的压力,这种场景就是缓存穿透(简单的说就是缓存和数据库中都没有某条数据,就会造成缓存穿透的情况)。

解决方案

  1. 布隆过滤器
    布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力。
    在这里插入图片描述
  2. 缓存空对象
    当存储层没有命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后在访问这个数据将会从缓存中获取,包含了后端数据库。
    在这里插入图片描述
    但是这种方法会存在两个问题:
  3. 如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键。
  4. 即使对空值设置了过期时间,还是会在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要一致性的业务会有影响(可以通过在代码中添加删除相应key的缓存来解决不一致的问题,比如增加,修改了相应的key直接删除该key对应的缓存即可)。

缓存击穿(量太大,缓存过期)

比如微博服务器在有热点事件时可能宕机。(同一时刻大量的访问在缓存中没有命中,砸向了数据库)

概述
这里需要注意和缓存穿透的区别,缓存击穿是指一个Key非常热点,在不停的扛着大并发,大并发集中对着一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开一个洞。
当某个key在过期的瞬间,有大量的请求并发访问,这类书籍一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且会写缓存,会导致使数据库瞬间压力过大。
解决方案
设置热点数据永不过期
从缓存层面来看,没有设置过期时间,所以不会出现热点key过期后产生的问题。
加分布式互斥锁
分布式锁:使用分布式锁,保证对于每个Key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,等待分布式锁释放。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。
在这里插入图片描述

缓存雪崩

概念
缓存雪崩,是指在某个时间段,缓存集中过期失效或者redis宕机。
产生雪崩的原因之一,比如在双十一的时候,大量的用户会去抢购一波商品,这波商品时间比较集中的放入缓存,假设缓存过期时间是一个小时,那么1个小时后,这批商品的缓存都获取了,而对这波商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。于是所有的请求都会到达存储层,存储层的调用量暴增,造成存储层可能挂掉的情况。
在这里插入图片描述
解决方案
redis高可用
这个思想的含义是,既然redis有可能挂掉,那就增加几台redis,这样1台挂掉还有其他的可以继续工作,就是搭建redis集群(解决redis宕机引起的缓存雪崩问题),可以使用异地多活。
限流降级(SpringCloud中有限流降级解决方案,停掉某些服务,保证主业务可用)
这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量,比如对某个Key只允许一个线程查询数据和写缓存,其他线程等待。
数据预热
数据预热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀(解决因为缓存集中过期而引起的缓存雪崩问题)。

参考链接

https://www.bilibili.com/video/BV1S54y1R7SB?p=36

猜你喜欢

转载自blog.csdn.net/tianzhonghaoqing/article/details/110144059