← 返回文章列表
数据库·813 次阅读

缓存穿透、击穿与雪崩:Redis 高可用三兄弟

缓存穿透、击穿与雪崩:Redis 高可用三兄弟

"缓存 + 数据库"是标准读架构,但缓存层在异常流量下有三种经典翻车方式,名字像但原因和解法完全不同。

缓存穿透:查的东西根本不存在

请求查询数据库里就没有的数据(如恶意构造不存在的 id),缓存自然也没有,每次请求都打到数据库。缓存形同虚设。

解法:

  1. 缓存空值:查不到也把 null 缓存起来(短 TTL,如 60 秒),挡住重复攻击
  2. 布隆过滤器(Bloom Filter):在缓存前加一层位图过滤器,快速判断"一定不存在 / 可能存在",不存在的直接拦截,适合海量 key、命中率稳定的场景
  3. 入口参数校验、对异常来源限流(配合 WAF)

缓存击穿:热点 key 突然过期

某个热点 key 过期的瞬间,海量并发同时涌来,全部穿过缓存打到数据库,一个点被"击穿"。

解法:

  1. 互斥锁:只允许一个线程重建缓存,其他线程等待后读缓存:
SETNX lock:post:1 1 EX 10  // 抢到锁才查库
// 未抢到:短暂 sleep 后重试读缓存
  1. 逻辑过期:value 中带逻辑过期时间,不依赖 TTL,发现逻辑过期后异步更新,当前请求仍返回旧值(不阻塞,容忍短暂脏数据)
  2. 热点数据永不过期 / 提前续期(结合访问统计)

缓存雪崩:大批缓存同时失效

大量 key 在同一时刻集中过期(或 Redis 整体宕机),请求洪流全部压向数据库,可能把 DB 打垮引发连锁雪崩。

解法:

  1. 过期时间加随机值:TTL = 基础时间 + random(0, 300s),打散失效时刻
  2. 缓存高可用:Redis 主从 + 哨兵/集群,单点故障自动切换;持久化保证快速恢复
  3. 多级缓存:本地缓存(Caffeine)+ Redis,一层挂了还有一层
  4. 服务端兜底:限流、降级、熔断,保护数据库不被打死(Sentinel 等)

三者对照

问题 根因 核心对策
穿透 数据不存在 空值缓存 + 布隆过滤器
击穿 单热点过期 互斥锁 / 逻辑过期
雪崩 大面积同时失效 随机 TTL + 高可用 + 限流

通用原则:缓存是用来"保护"数据库的,设计时要假设缓存会失效、会挂掉,并准备好故障时的降级路径,而不是让数据库裸奔。

看到这里了?如果这篇文章帮到过你

请我喝瓶可乐就好 🥤

收款码

评论0 条

还没有评论,来抢沙发~

发表评论

评论需审核后显示

© 2026 许冬博客 · 专注 JS 技术分享

·RSS 订阅·Powered by Nuxt 4