缓存穿透,雪崩,击穿
缓存穿透
缓存穿透指的是:一个缓存和数据库中都不存在的数据,由于数据库无法写入缓存,导致频繁请求直接打到数据库,从而造成数据库压力过大甚至被“打穿”。
常见的解决方法包括:缓存空值 或 布隆过滤器。
布隆过滤器由一个全 0 的位图数组和 n 个哈希函数组成。当一个数据在请求缓存前,会先经过布隆过滤器。过滤器会通过 n 个哈希函数计算出 n 个哈希值,再分别对数组长度取模,并将对应的数组下标置为 1。
查询时,只需要查看位图数组中这 n 个位置是否全部为 1:
- 若存在某个位为 0,则说明该数据一定不存在于数据库中;
- 若全部为 1,则说明该数据可能存在,但不一定真的存在,因为可能出现哈希碰撞。
因此,布隆过滤器判断“存在”时并不能保证数据真的存在,但判断“不存在”时一定准确。
缓存雪崩
缓存雪崩指的是:大量的缓存 Key 在同一时间失效,或者 Redis 服务器宕机,导致所有请求同时打到数据库,造成数据库瞬时压力过大,甚至宕机的情况。
解决方法:
为缓存设置 固定过期时间 + 随机过期时间,让不同 Key 的过期时间错开,避免在同一时间集中失效。
缓存击穿
缓存击穿指的是一个热点key设置了时间了过后 时间过期了 恰好这个时候大量请求打到数据库 让数据库压力大
解决方案:
方案一:互斥锁(分布式锁)
当缓存失效时,不立即去加载数据库,而是先使用 Redis 的 SETNX 命令设置互斥锁。
- 若设置成功(即当前线程获得锁),则执行
load db操作并回填缓存; - 若设置失败(说明已有线程在加载数据),则稍后重试获取缓存。
优点:保证数据一致性。
缺点:性能稍差,可能存在死锁风险。
方案二:逻辑过期
设置 Key 时,不给 Redis 设置真实的过期时间,而是在 Value 中自带一个逻辑过期时间字段。
实现思路如下:
- 设置缓存时,将过期时间作为字段与数据一起存入;
- 查询时,先从 Redis 获取数据并判断逻辑时间是否过期;
- 若已过期,则异步开启一个线程进行数据刷新,同时返回旧数据给用户(保证高可用)。
优点:高性能、高可用。
缺点:数据可能短时间内不一致。
总结:
- 若追求强一致性 → 使用 分布式锁方案;
- 若追求高性能、高可用性 → 使用 逻辑过期方案。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 彬子的Blog!



