---
title: 缓存三失效（穿透/击穿/雪崩）
type: concept
domain: redis
tags: [redis, cache, penetration, breakdown, avalanche, defense]
status: learning
created: 2026-09-20
last_reviewed: 2026-09-20
method: feynman
related_questions:
  - "什么是缓存击穿、缓存穿透、缓存雪崩"
related_knowledge:
  - ./cache-consistency.md
  - ./redis-expiration-eviction.md
visualizations: []
anki_cards: 5
interview_rounds:
  - "2026-09-20-round-1-Q2"
---

# 缓存三失效（穿透/击穿/雪崩）

> 三种问题根因不同（无效数据 / 单点失效 / 批量失效），防御手段也必须差异化。

## 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）

**根因**：批量失效 + 基础设施故障

**方案分层**：

| 层级 | 方案 | 说明 |
|------|------|------|
| 1 | TTL 加随机抖动 | `TTL = base + random(0, delta)`，避免同时过期 |
| 2 | Redis 高可用 | 主从 + 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 抖动 + 高可用 + 多级缓存 + 熔断

## 常见误区

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

## 延伸追问

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

## 速查表

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

## 关联题目（题库）

- 《什么是缓存击穿、缓存穿透、缓存雪崩》— 2026-09-20 Round 1 Q2, ⭐⭐⭐⭐☆（方案有层次，缺逻辑过期细节）

## 关联知识

- [缓存一致性](./cache-consistency.md)
- [Redis 过期与淘汰策略](./redis-expiration-eviction.md)
- [Redis 为什么快 + 为什么单线程](./redis-single-thread.md)

## Anki 候选卡片

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

---

*最后更新：2026-09-20*
