缓存雪崩 & 缓存穿透
2019-06-30 本文已影响27人
光剑书架上的书
缓存雪崩 & 缓存穿透
缓存雪崩 & 缓存穿透.png缓存流程
1.参数传入对象主键ID
2.根据key从缓存中获取对象
3.如果对象不为空,直接返回
4.如果对象为空,查询数据库
5.如果从数据库查询出的对象不为空,则放入缓存(设定过期时间)
缓存雪崩
如果我们的缓存挂掉了,这意味着我们的全部请求都跑去数据库了。
如果缓存数据设置的过期时间是相同的,并且Redis恰好将这部分数据全部删掉。
这就会导致在这段时间内,这些缓存同时失效,全部请求到数据库中。
缓存挂掉解决方案
-
事发前
- 主从架构+Sentinel
- Cluster
- 分布式缓存架构
- 设置过期标志更新缓存
- 使用锁或队列
- 二级缓存
-
事发中
- 设置本地缓存(ehcache)+限流(hystrix)
-
事发后
- 缓存持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据
缓存过期时间集中解决方案
- 过期时间设置随机
缓存穿透
查询缓存和数据库中都没有的数据
- 例如:查询一个一定不存在的数据
解决方案
-
使用布隆过滤器(BloomFilter)提前拦截
- 将所有可能存在的数据哈希到一个足够大的bitmap中,
一个一定不存在的数据会被这个bitmap拦截掉,
从而避免了对底层存储系统的查询压力。
- 将所有可能存在的数据哈希到一个足够大的bitmap中,
-
用户鉴权校验,id校验
-
缓存空对象,设置一个较短的过期时间,让其自动剔除
缓存击穿
爆炸查询缓存中没有但数据库中有的数据
解决方案
- 设置热点数据永远不过期
- 加互斥锁,防止都去数据库重复取数据,重复往缓存中更新数据情况出现
互斥锁(mutex lock)
-
只让一个线程构建缓存,其他线程等待构建缓存的线程执行完,
重新从缓存获取数据 -
单机
- 用synchronized或者lock
-
分布式
- 分布式锁,可以用memcache的add, redis的setnx, zookeeper的添加节点操作
缓存预热
系统上线后,将相关的缓存数据直接加载到缓存系统。
定时刷新缓存
缓存更新
定时去清理过期的缓存
缓存降级
保证核心服务可用
缓存与数据库双写不一致的问题
解决方案
-
将删除缓存、修改数据库、读取缓存等的操作
积压到队列里边,实现串行化 -
Cache Aside Pattern
- 将需要删除的key发送到消息队列中
- 自己消费消息,获得需要删除的key
- 不断重试删除操作,直到成功