缓存穿透、击穿与雪崩:Redis 高可用三兄弟
缓存穿透、击穿与雪崩:Redis 高可用三兄弟
"缓存 + 数据库"是标准读架构,但缓存层在异常流量下有三种经典翻车方式,名字像但原因和解法完全不同。
缓存穿透:查的东西根本不存在
请求查询数据库里就没有的数据(如恶意构造不存在的 id),缓存自然也没有,每次请求都打到数据库。缓存形同虚设。
解法:
- 缓存空值:查不到也把 null 缓存起来(短 TTL,如 60 秒),挡住重复攻击
- 布隆过滤器(Bloom Filter):在缓存前加一层位图过滤器,快速判断"一定不存在 / 可能存在",不存在的直接拦截,适合海量 key、命中率稳定的场景
- 入口参数校验、对异常来源限流(配合 WAF)
缓存击穿:热点 key 突然过期
某个热点 key 过期的瞬间,海量并发同时涌来,全部穿过缓存打到数据库,一个点被"击穿"。
解法:
- 互斥锁:只允许一个线程重建缓存,其他线程等待后读缓存:
SETNX lock:post:1 1 EX 10 // 抢到锁才查库
// 未抢到:短暂 sleep 后重试读缓存
- 逻辑过期:value 中带逻辑过期时间,不依赖 TTL,发现逻辑过期后异步更新,当前请求仍返回旧值(不阻塞,容忍短暂脏数据)
- 热点数据永不过期 / 提前续期(结合访问统计)
缓存雪崩:大批缓存同时失效
大量 key 在同一时刻集中过期(或 Redis 整体宕机),请求洪流全部压向数据库,可能把 DB 打垮引发连锁雪崩。
解法:
- 过期时间加随机值:
TTL = 基础时间 + random(0, 300s),打散失效时刻 - 缓存高可用:Redis 主从 + 哨兵/集群,单点故障自动切换;持久化保证快速恢复
- 多级缓存:本地缓存(Caffeine)+ Redis,一层挂了还有一层
- 服务端兜底:限流、降级、熔断,保护数据库不被打死(Sentinel 等)
三者对照
| 问题 | 根因 | 核心对策 |
|---|---|---|
| 穿透 | 数据不存在 | 空值缓存 + 布隆过滤器 |
| 击穿 | 单热点过期 | 互斥锁 / 逻辑过期 |
| 雪崩 | 大面积同时失效 | 随机 TTL + 高可用 + 限流 |
通用原则:缓存是用来"保护"数据库的,设计时要假设缓存会失效、会挂掉,并准备好故障时的降级路径,而不是让数据库裸奔。
看到这里了?如果这篇文章帮到过你
请我喝瓶可乐就好 🥤

评论0 条
还没有评论,来抢沙发~