缓存穿透击穿雪崩终极对比

1.1 一张表封神——画这个就够了


graph LR

    subgraph "缓存穿透"

        P1["查什么:数据库中不存在的数据"]

        P2["根因:恶意攻击 / 不存在的 ID"]

        P3["现象:每个不存在 ID 都打到 DB<br/>缓存完全没挡住"]

        P4["范围:不限量的不同 key"]

        P5["比喻:一直有人问'有大象吗?'"]

        P6["解法:①缓存空值 ②布隆过滤器"]

        P7["速记:查不存在的 → 两道门拦住"]

    end

    subgraph "缓存击穿"

        B1["查什么:数据库中存在的数据"]

        B2["根因:热点 key 刚好过期"]

        B3["现象:同一个热点 ID 的请求<br/>瞬间全部打到 DB"]

        B4["范围:单个 key"]

        B5["比喻:全班同时问老师同一个问题"]

        B6["解法:①互斥锁 ②逻辑过期"]

        B7["速记:热点刚好过期 → 只让一个人去拿"]

    end

    subgraph "缓存雪崩"

        C1["查什么:数据库中存在的数据"]

        C2["根因:大量 key 同时过期或 Redis 挂了"]

        C3["现象:所有请求绕过缓存<br/>全部打到 DB"]

        C4["范围:大量 key / 整个 Redis"]

        C5["比喻:学校同时下课食堂窗口被冲"]

        C6["解法:①随机过期 ②多级缓存<br/>③限流降级 ④Redis 高可用"]

        C7["速记:大片一起过期 → 别挤在一起"]

    end

1.2 连环追问 —— 怎么从”背答案”变成”你在思考”

 
延伸提问:说说缓存穿透怎么解决?
 
你:布隆过滤器 + 缓存空值。
 
延伸提问:布隆过滤器有什么缺点?
 
你:① 不能删除元素——商品下架后布隆过滤器里还在,只能重建
 
    ② 有误判率——说"可能存在"时可能是误判
 
    ③ 需要提前知道数据量——初始化时就要预估数组大小
 
延伸提问:误判会导致什么?
 
你:误判说"可能存在"→ 放行去查 Redis → Redis 也没有 → 查 MySQL → MySQL 也没有
 
    → 这次被穿透了。但这只是"漏网之鱼"——概率很低(1% 以内),
 
    比其他 99% 的流量被挡住,完全可接受。
 
    加一层缓存空值兜底——偶尔漏过去的也被短时间缓存住。
 
延伸提问:为什么布隆过滤器不能删除?
 
你:因为它多个元素共享 bit。一个格子被 A、B、C 三个元素涂过,
 
    你不能因为删了 A 就把这个格子清零——那样 B 和 C 也被"误删"了。
 
    所以只能整个过滤器重建。
 
延伸提问:缓存击穿用互斥锁有什么风险?
 
你:① 锁超时——查 MySQL 太慢导致锁自动释放 → 多个请求同时查 MySQL → 互斥失效
 
    ② 锁竞争——几千个请求同时抢锁,对 Redis 也是额外压力
 
    ③ 死锁——锁没设超时 + 拿到锁的请求崩了 = 锁永远不释放
 
延伸提问:那逻辑过期有什么风险?
 
你:① 数据一致性——返回给用户的可能是几秒前的旧数据
 
    ② 预热依赖——系统启动时必须把热点数据加载进 Redis,否则第一次还是穿透
 
    ③ 内存占用——热点 key 物理上永不过期,可能撑大 Redis 内存(需要监控)
 
延伸提问:缓存雪崩的随机过期时间真的能解决吗?
 
你:只能说"缓解"——把同时过期变成分散过期。但如果 Redis 本身挂了,
 
    随机过期也没用(Redis 都没了,谈什么过期)。所以雪崩需要多层防线——
 
    随机过期 + 本地缓存 + 限流降级 + 高可用集群,一层一层补。
 
延伸提问:那你觉得本地缓存会有什么问题?
 
你:① 数据不一致——多台服务器各自的本地缓存更新不同步,
 
      一台服务器缓存了新数据,另一台还是旧的
 
    ② 内存占用——每个进程各自维护一份缓存,总内存 = 单份 × 服务器数量
 
    ③ 冷启动——服务器重启后本地缓存是空的,需要从 Redis/MySQL 重新加载
 
    所以本地缓存只适合存"变更极少的热点数据"——配置项、首页 Banner 之类。
 

速记卡(面试闪卡)

Q1:一句话讲清「缓存穿透击穿雪崩终极对比」到底是什么?

A:缓存三兄弟:穿透查不存在数据、击穿热点 key 刚好过期、雪崩大量 key 同时失效,根因解法各不相同。

Q2:1.1 缓存穿透 —— 怎么理解?

A:穿透=查数据库里根本不存在的数据,每个不存在的 ID 都打到 DB、缓存完全没挡住,根因是恶意攻击/不存在的 ID,范围不限量的不同 key。类比一直有人问”有大象吗”。解法两道门:① 缓存空值 ② 布隆过滤器。

Q3:1.1 缓存击穿 —— 怎么理解?

A:击穿=查数据库里存在的数据,但热点 key 刚好过期,同一热点 ID 的请求瞬间全打到 DB,范围是单个 key。类比全班同时问老师同一个问题。解法:① 互斥锁(只放一个人去查)② 逻辑过期(物理不过期,异步刷新)。

Q4:1.1 缓存雪崩 —— 怎么理解?

A:雪崩=大量 key 同时过期或 Redis 直接挂了,所有请求绕过缓存全打到 DB,范围是大量 key/整个 Redis。类比学校同时下课食堂窗口被冲。解法多层:① 随机过期 ② 多级缓存 ③ 限流降级 ④ Redis 高可用。

Q5:1.2 连环追问(布隆/锁/雪崩防御) —— 怎么理解?

A:布隆过滤器缺点:不能删(多元素共享 bit,清零会误删别人)、有误判率、需预估大小;误判只是低概率漏网,加缓存空值兜底。互斥锁风险:锁超时/锁竞争/死锁;逻辑过期风险:旧数据/预热依赖/内存撑大。雪崩随机过期只能”缓解”,Redis 挂了没用,需多层防线。

Q6:核心速记主线有哪些?

  • 穿透:查不存在的→缓存空值+布隆过滤器

  • 击穿:热点 key 过期→互斥锁+逻辑过期

  • 雪崩:大量 key 同失效/Redis 挂→随机过期+多级缓存+限流+高可用

  • 布隆缺点:不可删、有误判、需预估大小

  • 互斥锁风险:超时/竞争/死锁;雪崩需多层防线

口诀

A:三兄弟名不同,穿透击穿雪崩

查无布隆拦门口,热点锁独扛

大片同失效,随机过期分散忙

多级缓存加限流,高可用才稳当

相关链接