一、缓存穿透
1.1 什么是缓存穿透
缓存穿透是指查询一个根本不存在的数据,缓存层和存储层都不会命中,通常处于容错考虑,如果存储层查不到数据则不写入缓存层,从而导致不存在的数据每次请求都要到存储层去查询,失去了缓存保护后端的意义。
1.2 造成的原因
造成缓存穿透的基本原因有两个。
- 自身业务代码或者数据出现问题
- 恶意攻击、爬虫等造成大量空命中
1.3 如何解决
-
缓存空结果
对于查询为空的请求,可以将这个空结果也缓存一段时间,设置一个较短的过期时间
-
使用布隆过滤器
在查询数据前,现在布隆过滤器中检查请求的数据是否存在,如果不存在,则直接返回错误,先不去查询数据库
二者对比
解决缓存穿透 | 优点 | 缺点 |
---|---|---|
缓存空对象 | 1. 代码维护简单 | 1. 数据不一致 2. 需要过多的缓存空间 3. 需要设置合理的过期时间 |
布隆过滤器 | 1. 缓存空间占用少 | 1. 代码复杂 2. 存在假阳性 3. 数据变化时,需要更新布隆 过滤器 |
二、缓存击穿
2.1 什么是缓存击穿
缓存击穿是指在高并发情况下,某个缓存失效时,所有请求同时访问数据库,导致数据库瞬时承受大量请求的情况。这种情况通常发生在某个热点数据的缓存失效时。
2.2 造成的原因
- 热点数据:某些数据被频繁访问,一旦缓存失效,所有请求都直接打到数据库。
- 缓存过期:设置的缓存过期时间较短,导致短时间内大量请求同时查询数据库。
2.3 如何解决
- 加锁机制:当请求到达时,先尝试获取一个分布式锁(如SETNX命令)。只有获取到所得请求才能去数据库查询数据,其他请求等待锁释放。查询完成后,其他请求就可以查缓存了,不用查数据库了。
- 提前更新缓存:在缓存即将过期时,提前刷新缓存。可以通过定时任务或在访问时判断,主动更新缓存。
- 设置合理的过期时间:对于热点数据,可以设置较长的过期时间。
三、雪崩优化
3.1 什么是缓存雪崩
由于缓存层承载着大量请求,有效地保护了存储层,但是如果存储层由于某些原因不能提供服务,于是所有的请求都会打到存储层,存储层的调用量会暴增,造成存储层也会级联宕机的情况。
3.2 如何解决
- 保证缓存层服务高可用性。如果缓存层设计成高可用的,即使个别节点、个别机器、甚至机房宕掉,依然可以提供服务,例如前面介绍的Redis Sentinel和Redis Cluster都实现了高可用。
- 使用双缓存。对于qps请求高的数据,可以使用两个层次的缓存(主缓存和备缓存),有效地减少缓存失效的概率。
- 限流和降级。对请求进行限流,控制流量,或者在高峰期进行服务降级,返回一些默认数据,保证服务稳定性。