Redis缓存穿透和雪崩

Redis缓存的使用 极大的提升了应用程序的性能和效率 特别是数据查询方面 但同时也带来了一些问题 其中最要害的问题就是 数据的一致性问题 从严格意义上讲 这个问题无解 如果对数据的一致性要求很高 那么就不能使用缓存

另外一些典型问题就是 缓存穿透 缓存雪崩 缓存击穿

缓存穿透

概念

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

风险 利用不存在的数据进行攻击 造成数据库压力过大

解决方案

布隆过滤器

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

image-20200625085817844

缓存空对象

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

image-20200625090048176

存在两个问题

  • 如果空值能被存储起来 这就意味着缓存需要更多的空间存储更多的键 因为这当中可能有很多空值的键
  • 即使对空值设置了过期时间 还是会存在缓存层和存储层的数据会有一段时间窗口不一致 这对于需要保持一致性的业务会有影响

缓存雪崩

缓存雪崩 是指在某一个时间段 缓存集中过期集体失效 或者redis宕机

image-20200625091206148

image-20200625091216617

image-20200625091443766

image-20200625091544234

缓存击穿

缓存击穿 是指一个key非常热点 在不停地扛着大并发 大并发集中对这个点进行访问 当这个key在失效的瞬间 持续的大并发 就穿破缓存 直接请求数据库 就像在一个屏障上凿开了一个洞

解决方案

设置热点数据永不过期

从缓存层面来看 没有设置过期时间 所以不会出现热点key过期后产生的问题

加互斥锁

分布式锁 使用分布式锁 保证对于每个key同时只有一个线程去查询后端服务 其他线程没有获得分布式锁的权限 因此 只需要等待即可 这种方式将高并发的压力转移到分布式锁 因此对分布式锁的考验很大

image-20200807185751795

资料参考:狂神说java