缓存雪崩 & 缓存穿透

缓存雪崩 & 缓存穿透

缓存雪崩 & 缓存穿透.png

缓存流程

1.参数传入对象主键ID

2.根据key从缓存中获取对象

3.如果对象不为空,直接返回

4.如果对象为空,查询数据库

5.如果从数据库查询出的对象不为空,则放入缓存(设定过期时间)

缓存雪崩

如果我们的缓存挂掉了,这意味着我们的全部请求都跑去数据库了。

如果缓存数据设置的过期时间是相同的,并且Redis恰好将这部分数据全部删掉。

这就会导致在这段时间内,这些缓存同时失效,全部请求到数据库中。

缓存挂掉解决方案

  • 事发前

    • 主从架构+Sentinel
    • Cluster
    • 分布式缓存架构
    • 设置过期标志更新缓存
    • 使用锁或队列
    • 二级缓存
  • 事发中

    • 设置本地缓存(ehcache)+限流(hystrix)
  • 事发后

    • 缓存持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据

缓存过期时间集中解决方案

  • 过期时间设置随机

缓存穿透

查询缓存和数据库中都没有的数据

  • 例如:查询一个一定不存在的数据

解决方案

  • 使用布隆过滤器(BloomFilter)提前拦截

    • 将所有可能存在的数据哈希到一个足够大的bitmap中,
      一个一定不存在的数据会被这个bitmap拦截掉,
      从而避免了对底层存储系统的查询压力。
  • 用户鉴权校验,id校验

  • 缓存空对象,设置一个较短的过期时间,让其自动剔除

缓存击穿

爆炸查询缓存中没有但数据库中有的数据

解决方案

  • 设置热点数据永远不过期
  • 加互斥锁,防止都去数据库重复取数据,重复往缓存中更新数据情况出现

互斥锁(mutex lock)

  • 只让一个线程构建缓存,其他线程等待构建缓存的线程执行完,
    重新从缓存获取数据

  • 单机

    • 用synchronized或者lock
  • 分布式

    • 分布式锁,可以用memcache的add, redis的setnx, zookeeper的添加节点操作

缓存预热

系统上线后,将相关的缓存数据直接加载到缓存系统。

定时刷新缓存

缓存更新

定时去清理过期的缓存

缓存降级

保证核心服务可用

缓存与数据库双写不一致的问题

解决方案

  • 将删除缓存、修改数据库、读取缓存等的操作
    积压到队列里边,实现串行化

  • Cache Aside Pattern

    • 将需要删除的key发送到消息队列中
    • 自己消费消息,获得需要删除的key
    • 不断重试删除操作,直到成功

Kotlin 开发者社区

国内第一Kotlin 开发者社区公众号,主要分享、交流 Kotlin 编程语言、Spring Boot、Android、React.js/Node.js、函数式编程、编程思想等相关主题。
Kotlin 开发者社区 QRCode.jpg

推荐阅读更多精彩内容