缓存三失效(穿透/击穿/雪崩)

redis 📚 learning cache-three-failures · redis · cache · penetration · breakdown · avalanche · defense

TL;DR(30 秒扫完)

  • 三失效 = 三种根因:穿透=无效 key、击穿=热点 key 失效、雪崩=批量失效
  • 防御分层:入口校验 → 布隆过滤器 → 互斥锁/逻辑过期 → TTL 抖动 → 高可用 → 多级缓存 → 限流熔断
  • 布隆过滤器:预加载有效 ID,误判率 1%,不支持删除,需定期重建
  • 逻辑过期:值里存 expireTime,物理 TTL 永不过期,适合高并发容忍读旧

关键结论

结论 A三问题常同时出现(如电商秒杀),防御体系必须分层叠加
结论 B布隆过滤器有静态限制,新增数据要同步更新,误判率权衡精度和内存
结论 C雪崩根因是批量失效 + 基础设施故障,单靠应用层防御不够,需要 Redis 高可用
结论 D缓存空值是最后兜底手段,但要设短 TTL 防缓存爆炸

完整讲解(费曼四步)

STEP 1 · 概念

缓存三失效是缓存系统中的三种典型故障模式:
  • 穿透:请求不存在的数据,每次都打到 DB
  • 击穿:热点 key 过期,瞬间并发穿透到 DB
  • 雪崩:大批 key 同时过期或 Redis 整体不可用,DB 被打爆
三者根因不同,防御手段必须差异化。

STEP 2 · 大白话

图书馆比喻:
  • 穿透:有人反复查一本图书馆根本没有的书,每次都去书架找一遍 → 需要"不存在书目黑名单"
  • 击穿:一本热门书被借走还没还,几百人同时来借 → 需要"预借排队机制"
  • 雪崩:图书馆突然停电,所有书都借不了,大家全部涌到出版社 → 需要"备用图书馆"

STEP 3 · 底层

缓存穿透(Cache Penetration)

根因:数据不存在 → 无 key 可存 → 无缓存可查 方案分层:
层级方案说明
1入口参数校验参数校验、鉴权、限流,提前拦截非法 ID
2布隆过滤器预加载所有有效 ID,误判率可控(推荐 1%)
3空值缓存DB 查不到缓存 null,TTL 短(30s-1min)
4风控兜底同一 IP 高频无效请求 → 封禁 / 验证码
布隆过滤器细节:
  • 启动时把所有有效 ID 载入 Bloom Filter
  • 请求先判存在性,不存在直接返回
  • 不支持删除,新增数据要同步更新
  • 误判率权衡:1% 误判率需要约 1.4 倍空间
  • 动态更新:用 Count-Min Sketch 或 RedissonBloom 支持动态扩容
空值缓存的副作用:恶意请求可撑爆缓存,所以 TTL 要短(30s-1min)

缓存击穿(Cache Breakdown)

根因:单热点 key 过期 + 并发请求 方案三档:
方案机制适用
互斥锁重建SET key_lock NX PX 10000,拿到锁查 DB 回填,其余等待中等并发
逻辑过期值结构存 expireTime,物理 TTL 永不过期,发现过期后异步重建高并发容忍读旧
永不过期 + 后台刷新定时任务提前刷新热点数据核心热点数据
互斥锁细节:
  • 用 Redis 的 SETNX 实现互斥锁
  • 锁超时时间要 > 业务耗时(一般 10s)
  • 其他线程短轮询读缓存,避免阻塞
逻辑过期细节:
  • 值结构:{data: "...", expireTime: 1700000000}
  • 物理 TTL 设为永不或超长(如 7 天)
  • 发现 expireTime < now 后异步重建
  • 容忍短暂读旧,但避免并发穿透

缓存雪崩(Cache Avalanche)

根因:批量失效 + 基础设施故障 方案分层:
层级方案说明
1TTL 加随机抖动TTL = base + random(0, delta),避免同时过期
2Redis 高可用主从 + Sentinel / Cluster,故障自动切换
3多级缓存本地缓存(Caffeine)+ Redis + DB
4限流熔断Sentinel / Hystrix,DB 压力大时快速失败
5预热定时刷新热点数据,重启前主动加载
TTL 抖动细节:
  • 例:所有商品详情 TTL = 3600 + random(0, 3600)(1-2 小时)
  • 避免整点大量 key 同时过期
多级缓存细节:
  • L1:Caffeine(本地,TTL 极短 1-5s)
  • L2:Redis(分布式,TTL 1-10min)
  • L3:DB(最终一致)
  • 一致性靠 Cache-Aside + 发布订阅

STEP 4 · 简化

一句话总结:穿透防无效、击穿防单点、雪崩防批量。防御分层叠加,布隆+互斥+抖动+高可用+多级+熔断。 记忆口诀:
  • 穿透 → 布隆过滤器 + 空值缓存
  • 击穿 → 互斥锁 + 逻辑过期
  • 雪崩 → TTL 抖动 + 高可用 + 多级缓存 + 熔断

常见误区

说"布隆过滤器能支持删除"
标准布隆过滤器不支持删除,需用 Count-Min Sketch
说"逻辑过期完全无副作用"
容忍短暂读旧,不适用于强一致场景
说"空值缓存可以 TTL 很长"
恶意请求可撑爆缓存,TTL 要短(30s-1min)
说"雪崩只要加 TTL 抖动就能防"
TTL 抖动防批量失效,但防不了 Redis 宕机,需要高可用 + 多级缓存

延伸追问

布隆过滤器不支持删除怎么办?数据新增如何同步?
Count-Min Sketch 支持计数减一;新增数据写入时同步 hash 进过滤器;或用 RedissonBloom 支持动态扩容
逻辑过期如何避免时钟漂移导致大量过期?
用 Redis 服务端时间;或改用 Redis TTL 但配合互斥锁
多级缓存的一致性问题怎么解决?
Cache-Aside + 发布订阅;本地缓存 TTL 极短(秒级);业务容忍短暂不一致
秒杀场景如何设计缓存防御体系?
预热库存到 Redis + Lua 原子扣减 + 布隆过滤 + 消息削峰 + 空单降级
Redis 集群整体宕机,你的系统如何优雅降级?
熔断打开 + 静态兜底数据 + 排队限流 + 前端提示

速查表

三失效: 穿透(无效) / 击穿(单点) / 雪崩(批量)
穿透防御: 入口校验 → 布隆过滤器 → 空值缓存 → 风控
击穿防御: 互斥锁 / 逻辑过期 / 永过期+后台刷新
雪崩防御: TTL抖动 → 高可用 → 多级缓存 → 限流熔断
布隆: 预加载+误判率1%+不支持删除+需定期重建
逻辑过期: 值存expireTime+物理TTL永不+容忍读旧
空值缓存: TTL 30s-1min+防缓存爆炸

Anki 候选卡片

Q: 缓存三失效的根因分别是什么?
A: 穿透=无效 key、击穿=热点 key 失效、雪崩=批量失效
Q: 布隆过滤器的限制?
A: 不支持删除、新增数据需同步更新、有误判率(推荐 1%)
Q: 缓存击穿三档方案?
A: 互斥锁重建、逻辑过期、永不过期+后台刷新
Q: 空值缓存的 TTL 设多久?
A: 30s-1min,防止恶意请求撑爆缓存
Q: 缓存雪崩的 5 层防御?
A: TTL 抖动 → 高可用 → 多级缓存 → 限流熔断 → 预热

关联题目

  • 《什么是缓存击穿、缓存穿透、缓存雪崩》— 2026-09-20 Round 1 Q2, ⭐⭐⭐⭐☆(方案有层次,缺逻辑过期细节)
  • 关联知识

    三失效根因不同:穿透=无效 key、击穿=热点 key 失效、雪崩=批量失效
    三失效像三个不同问题:穿透是查不存在的人;击穿是抢一个爆款;雪崩是全场断电
    ✦ 记 忆 口 诀 ✦
    根因不同防御必须差异化:入口校验→布隆→互斥→TTL 抖动→高可用
    关键可视化
    三失效对比
    flowchart TB
      C["缓存失效"] --> P["穿透<br/>无效 key<br/>每次都打到 DB"]
      C --> B["击穿<br/>热点 key 过期<br/>瞬间并发穿透"]
      C --> A["雪崩<br/>批量 key 同时过期<br/>或 Redis 整体宕机<br/>DB 被打爆"]
    防御分层体系
    flowchart LR
      L1["1.入口校验<br/>参数合法性"] --> L2["2.布隆过滤器<br/>预加载有效 ID"]
      L2 --> L3["3.互斥锁/逻辑过期<br/>热点 key 只让一个请求"]
      L3 --> L4["4.TTL 抖动<br/>随机延迟防批量失效"]
      L4 --> L5["5.Redis 高可用<br/>哨兵/Cluster"]
      L5 --> L6["6.多级缓存<br/>本地 Caffeine"]
      L6 --> L7["7.限流熔断<br/>保护 DB"]
    布隆过滤器
    flowchart LR
      I["请求 key"] --> B{"布隆过滤器"}
      B -->|可能存在| C["查缓存/DB"]
      B -->|一定不存在| R["直接返回"]
      subgraph 特点
        F1["误判率 1%"]
        F2["不支持删除"]
        F3["需定期重建"]
        F4["内存极省"]
      end
    知识关系

    ⬆️ 前置(Prerequisite)

    redis-single-thread

    🔄 延伸(Extends)

    暂无

    ⚡ 对比(Contrast)

    缓存一致性— 一致性是写侧问题(DB 与缓存不同步),三失效是读侧问题(缓存被击穿到 DB)过期与淘汰— 雪崩根因之一是 TTL 集中过期,与淘汰策略有交集
    🎯 概念 📏 规则 ⚠️ 误区 🔍 追问 ✨ 口诀 共 0 张卡,点击翻面