在高并发的系统架构中,Redis 缓存就像是我们系统的“防弹衣”,帮我们挡下了绝大多数的数据库请求。可要是这件防弹衣没穿对,或是碰上了特殊的“子弹”,反而可能捅出更大的娄子。
缓存穿透、缓存击穿和缓存雪崩,光听名字就够绕的。虽然它们最终的表征都是数据库压力暴增,但背后的触发机制、波及范围和应对手段却完全不在一个维度上。在 云栈社区 的技术板块里,关于这三者的讨论也一直是高频热点。
下面,我们通过几个维度的对比,把它们的区别彻底掰扯清楚。
三者区别
| 维度 |
缓存穿透 |
缓存击穿 |
缓存雪崩 |
| 核心定义 |
查询根本不存在的数据 |
单个热点 Key 失效 |
大量 Key 同时失效或宕机 |
| 触发原因 |
恶意攻击(如 ID=-1)或业务误操作 |
热点数据(如秒杀商品)刚好过期 |
1. 批量 Key 设置相同 TTL 2. Redis 服务宕机 |
| 数据状态 |
缓存无,数据库也无 |
缓存无(过期),数据库有 |
缓存批量无,数据库有 |
| 影响范围 |
针对特定无效 Key,长期攻击会耗尽 DB 资源 |
针对单个热点 Key,瞬间并发极高 |
全局性影响,可能导致系统整体瘫痪 |
| 典型场景 |
爬虫遍历 ID、参数校验缺失 |
微博热搜、整点秒杀、爆款商品 |
凌晨系统重启、缓存集群故障 |
详细解析
| 问题类型 |
详细场景描述 |
核心解决方案 |
方案优缺点分析 |
| 缓存穿透 |
用户请求的数据在缓存和数据库里压根儿就没有。每次请求都会直接绕过缓存,怼到数据库上。如果攻击者恶意用不存在的 Key 进行高频请求,数据库很可能因为处理大量无效查询而宕机。 |
1. 布隆过滤器 2. 缓存空对象 |
布隆过滤器:内存占用极小,查询效率高;但存在误判率,且不支持删除。 缓存空对象:实现简单;但需设置较短过期时间(如 5 分钟),否则会占用额外内存。 |
| 缓存击穿 |
某个 Key 是超级热点的数据(比如一场火爆的活动)。在它过期的那一刹那,海量并发请求砸过来,发现缓存没了,就会瞬间全部涌向数据库,导致库压力瞬时拉满。这在高并发场景下是典型的“针尖上的舞蹈”。 |
1. 互斥锁 2. 逻辑过期 |
互斥锁:保证数据一致性,但会降低吞吐量,其他线程需排队等待。 逻辑过期:不设物理过期时间,数据里带一个逻辑过期字段。发现过期后异步更新,直接返回旧数据,高可用但存在短暂不一致。 |
| 缓存雪崩 |
大量 Key 跟约好了似的在同一时间失效(比如设置了相同的过期时间),或者 Redis 服务直接罢工了。这导致原本由 缓存 扛住的海量请求,一股脑全压到数据库上,极易引发系统性的崩溃。 |
1. 随机过期时间 2. 多级缓存 3. 限流降级 |
随机 TTL:在基础过期时间上增加随机值,避免集体失效,是最简单有效的一招。 多级缓存:本地缓存 + 分布式缓存,多加一层容错保障。 限流降级:当数据库压力过大时,直接拒绝部分请求或返回兜底默认值。 |
总结
在生产环境中,这三种问题很少会单打独斗地出现。要构建一个高可用的缓存系统,建议把下面这套最佳实践刻在脑子里:
- 预防为主:设计之初就规划好 Key 的过期策略,坚决杜绝“一刀切”的固定过期时间。
- 多重防御:布隆过滤器拦截无效请求,互斥锁保护热点数据,多手准备才能防患于未然。
- 兜底机制:不管缓存策略设计得多精妙,都必须给数据库配上限流和降级方案,保证极端情况下核心业务不挂。
- 监控告警:实时盯住缓存命中率、数据库 QPS 和系统负载,一旦嗅到异常(比如 QPS 突增),立刻触发告警介入。

|