Version: Next

缓存穿透与缓存雪崩

分布式缓存系统存在的问题

  • 一致性问题(难以彻底解决)
  • 缓存穿透
  • 缓存雪崩
  • 缓存击穿

缓存穿透(查不到)

概念

查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询,发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透

解决方案:

  • 空值缓存
  • 布隆过滤器

布隆过滤器

布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则 丢弃,从而避免了对底层存储系统的查询压力

空值缓存

当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数 据将会从缓存中获取,保护了后端数据源

空值缓存存在的问题

  • 由于 Redis 是单线程串行的,在设置 null key 之前的请求一定会穿透到数据库
  • 因此可以提前加锁在 redis 上,使用 setnx ,设置成功等于获取成功,否则获取失败

存在问题:

  • 缓存控制会消耗资源
  • 即使设置了过期时间,还是会导致缓存层和存储层数据存在数据不一致的窗口期,对一致性造成影响

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

指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,造成数据库崩溃

这类数据往往是热点数据

解决方案

  • 设置热点数据永不过期

  • 互斥锁

    分布式锁:使用分布式锁,保证对每个key同时只有一个线程去查询后端服务,其他线程没有获取分布式锁的权限,因此只需等待即可

    这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大


缓存雪崩(集中失效|宕机|停电)

缓存雪崩,是指在某一个时间段,缓存集中过期失效

image-20200714165941717

缓存集中过期失效

有一堆缓存,它们的过期时间都一样,那么到了过期的时刻,它们就集体失效了,此时新的请求就会打到数据库上,如果这种请求量很大,就会体现为周期性的缓存失效,形成周期性的持久层数据库访问压力,也有可能导致数据库崩溃

缓存服务器宕机或停电

相当于缓存层直接没了,缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。

解决方案

  • redis高可用

    搭建Redis集群,防止整个缓存层挂掉

  • 限流降级

    在缓存失效后,通过加锁或者队列控制数据库写缓存的线程数

  • 数据预热

    在正式部署前,先把可能被访问的数据访问一边,这样一来可能被大量访问的数据就被加载到了缓存中

    在即将发生大规模并发访问前手动触发缓存中不同的key,设置不同的缓存过期时间,避免缓存集中失效