本文最后更新于2 天前,其中的信息可能已经过时,如有错误请发送邮件到2156936367@qq.com
前言
我们都知道缓存可以减少数据库压力、加快查询效率、还可以解决热点读的问题,这都是缓存的好处,那缓存有什么坏处呢?
比如说,缓存没有挡住压力,让请求都打到了数据库,这不就轧钢了,这个问题就是缓存的问题了
缓存雪崩、缓存击穿、缓存穿透的本质就是:缓存没有挡住流量,导致请求直接打到后端数据库 / 服务,最终引发数据库压力暴涨、接口超时、服务雪崩。
他们三者的区别就是:缓存为什么没有挡住流量?
缓存雪崩
什么是缓存雪崩?
大量缓存 key 在同一时间失效,或者整个缓存服务集群不可用,导致原本应该由缓存承接的流量,瞬间全部打到数据库。
正常情况其实是:Redis直接命中,然后直接返回
缓存雪崩是什么情况呢:大量key同时过期或者整个Reids集群挂了,请求全部直接打到了数据库,数据库连接数暴涨,慢查询、锁等待、CPU飙升…、接口超时、服务线程池耗尽、最终导致整个系统雪崩
解决方案
- 过期时间加随机值,不要让大量 key 同一时间过期。
TTL = 3600s + random(0, 600s)
- 热点数据永不过期,后台异步刷新
- 逻辑过期:热点 key 不设置物理过期时间,而是在 value 里面保存逻辑过期时间,没过期的话直接返回;过期的话返回旧数据,后台异步刷新,这样有一个问题(数据短暂不一致)
- Redis 高可用架构:主从、哨兵、集群、自动故障转移、多地容灾
- 限流、降级、熔断、MQ消息队列(从整个架构的视角)
缓存击穿
什么是缓存击穿?
某一个热点 key 在失效瞬间,大量并发请求同时访问这个 key,导致这些请求全部打到数据库。
与缓存雪崩不一样的是:他是热点key失效、不是所有key同时失效,导致这个热点key直接被打穿
比如说秒杀系统:一个热销爆款商品的key突然失效,那直接GG,数据库被打爆
解决方案
- 互斥锁:当热点 key 失效时,只允许一个请求去查数据库并重建缓存,其他请求等待或者稍后重试。
- 逻辑过期
- 热点数据永不过期,后台异步刷新
- 提前预热热点key:在大促开始前,提前把热key 写入缓存
缓存穿透
什么是缓存穿透?
请求的数据在缓存中不存在,在数据库中也不存在。每次请求都会绕过缓存,直接打到数据库。
用户请求不存在的数据,redis查不到,数据库也查不到,无法写入缓存,下次请求还是查数据库。
如果有人恶意构造大量不存在数据的ID,就很可能直接打爆数据库,缓存穿透请求一般都是非法恶意的
解决方案
- 缓存空值 NULL:如果数据库查不到,也把空结果(NULL)缓存起来。但是空值缓存 TTL 不宜太长(一般是30s ~ 5 min),如果后面数据库真的新增了这个 userId,但 Redis 里还缓存着 null,就会导致短时间数据不一致
- 布隆过滤器 BloomFilter:布隆过滤器用于判断一个数据可能存在还是一定不存在。比如说请求进来后,先经过布隆过滤器进行判断,如果缓存和数据库都不存在,就直接拒绝进入缓存,如果判断存在,再查缓存和数据库
- 优点:内存占用小,适合拦截大量非法 key
- 缺点:有误判率,不能删除普通元素
- 参数校验:很多穿透请求是明显非法的,这些请求应该在入口层直接拦截
- 风控、限流、黑名单:如果穿透是攻击行为,需要做安全防护
对比
| 对比项 | 缓存雪崩 | 缓存击穿 | 缓存穿透 |
|---|---|---|---|
| 本质 | 大量缓存同时失效或缓存层不可用 | 热点 key 失效 | 查询不存在的数据 |
| key 数量 | 大量 key | 一个或少数热点 key | 大量不存在的 key |
| 数据库中是否存在 | 通常存在 | 存在 | 不存在 |
| 是否热点 | 不一定 | 是 | 不一定 |
| 主要风险 | 大面积请求打到数据库 | 单个热点请求打爆数据库 | 恶意无效请求绕过缓存 |
| 常见原因 | TTL 集中、Redis 宕机 | 热点 key 过期 | 非法参数、恶意攻击 |
| 核心方案 | TTL 随机、高可用、限流降级 | 互斥锁、逻辑过期、热点预热 | 空值缓存、布隆过滤器、参数校验 |
总结
- 缓存雪崩、击穿、穿透都是缓存失效后导致请求打到数据库的问题,但触发原因不同。
- 缓存雪崩是大量 key 同时失效,或者 Redis 整体不可用,导致大量请求瞬间打到数据库。常见解决方案是 TTL 加随机值、热点数据预热、Redis 高可用、限流降级和熔断。
- 缓存击穿是某个热点 key 过期,在高并发下大量请求同时查数据库。解决方案一般是互斥锁、逻辑过期、热点 key 永不过期、后台异步刷新。
- 缓存穿透是请求的数据本身不存在,缓存和数据库都查不到,导致每次请求都打到数据库。常见解决方案是缓存空值、布隆过滤器、参数校验、限流和黑名单。
当真的出现Redis事故,SRE该如何解决?
- 首先就是止血(限流、降级、熔断)
- 再定位(缓存雪崩、击穿、穿透)
- 恢复(根据问题类型处理)
- 复盘做长期治理
希望你对该篇文章Redis缓存问题有更深刻的理解,感谢观看~


