常见缓存失效问题及解决方案

120 阅读3分钟

二、常见缓存失效问题及解决方案

在缓存中常常会被提到问题:缓存穿透、缓存击穿、缓存雪崩。 下面我们就简单解释一下它们是什么以及如何解决?

缓存穿透: 指的是当访问实际不存在的数据时,该请求全部都打到数据库上面,导致缓存失效。

解决方案:缓存空对象、布隆过滤器

  1. 缓存空对象:
  • 流程:对未查到的数据也进行缓存,以减少对数据库的缓存
  • 优点:实现简单,便于维护
  • 存在问题:导致内存的消耗以及可能出现短期的不一致,可通过TTL解决
  1. 布隆过滤器: 可理解为一个byte[] 里面存储的是二进制数据,也就是将数据库里面的数据通过特定的hash算法得到的hash值存储到布隆过滤器中,布隆过滤器只需要查找某个位置的值是0还是1就可以知道数据是否存在。
  • 过程:首先请求会来到布隆过滤器,如果存在就会则放行,走缓存和数据,如果不存在就直接拒绝
  • 优点:内存占用少,没有多余的存储key
  • 存在问题:布隆过滤器的结果可能不正确,仍然存在穿透风险,但是需要知道的一点是布隆过滤器的结果说数据存在就不一定正确,但是不存在那么一定正确。

上面的两种方案其实还是属于被动的方案,我们其实还可以做一些主动的方案:

  • 增强id的复杂度,避免攻击者猜到id的规律,通过数据基础格式的校验来防止
  • 加强用户权限校验,比如什么用户可以访问,需要登录,用户的访问频率
  • 也可以做好热点参数的限流,比如有些内容访问比较多,就限流

缓存雪崩: 指的是大量的key同时失效或者redis服务端宕机,导致大量的请求打到数据库,造成服务器压力

解决方案:随机过期时间、多级缓存、集群或者哨兵提高服务的可用性、给缓存添加降级限流策略

这块的内容大概的讲解一下:随机过期时间,在TTL中添加随机值,多级缓存可以利用浏览器,nginx,jvm来缓存数据。集群主要是针对redis在三高中出现宕机,通过主从来实现服务的高可用和稳定。而限流降级针对的是服务全挂(机房断电),通过拒绝服务让其不用打到数据库

缓存击穿: 指的是热点key失效,导致大量请求打到数据库上

解决方案:互斥锁、逻辑过期

  1. 互斥锁:让一个请求拿到锁,去数据库查询数据,然后写回缓存,需要注意的是没有拿到锁的请求不能一种去获得锁,需要休眠一会。其余请求只能等待,性能较差
  2. 逻辑过期:只是在redis中不设置过期,但是这样就会导致数据会不一致,那么我们就需要通过设置逻辑过期来进行解决该问题