1. 缓存穿透
- 概念
-
用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。
-
当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库
。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。 -
与缓存击穿区别
- 缓存击穿,
是指一个key非常热点,在不停的扛着大并发
,大并发集中对这一个点进行访问 - 当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
- 缓存击穿,
-
- 解决方案
- 布隆过滤器
- 布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力。
- 缓存空对象
- 当存储层没有命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后在访问这个数据将会从缓存中获取,包含了后端数据库。
- 但是这种方法会存在两个问题:
- 如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键
- 即使对空值设置了过期时间,还是会在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要一致性的业务会有影响(可以通过在代码中添加删除相应key的缓存来解决不一致的问题,比如增加,修改了相应的key直接删除该key对应的缓存即可)。
- 布隆过滤器
2. 缓存击穿
- 三个条件
- 数据库访问压力瞬时增大
- redis中没有出现大量key过期
- redis正常运行,数据库崩了
- 原因
- redis某个key过期了,大量访问使用这个key
- 解决方案
预先设置热门数据,
访问高峰之前,把热门数据缓存到redis中适时调整
,现场监控哪些数据热门,实时调整key的过期时常使用锁
- 使用分布式锁,保证对于每个Key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,等待分布式锁释放。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。
3. 缓存雪崩
- 概念
- 缓存雪崩,是指在某个时间段,
缓存集中过期失效
或者redis宕机
- 产生雪崩的原因之一,比如在双十一的时候,大量的用户会去抢购一波商品,这波商品时间比较集中的放入缓存,假设缓存过期时间是一个小时,那么1个小时后,这批商品的缓存都获取了,而对这波商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。
- 于是所有的请求都会到达存储层,存储层的调用量暴增,造成存储层可能挂掉的情况。
- 缓存雪崩,是指在某个时间段,
- 解决方案
- redis高可用,集群
- 构建多级缓存架构:nginx,redis,其他缓存
- 使用锁或队列
- 设置过期标志更新缓存
- 记录缓存数据是否过期(设置提前量), 如果过期,就触发其他线程更新redis的key
- 将缓存失效时间分散开
- 失效时间加上一个随机值,比如1-5分钟随机,这样每一个缓存过期时间的重复率就会降低