Appearance
缓存穿透与缓存击穿:场景与解决方案
在高并发系统里,缓存是保护数据库和提升延迟表现的关键组件。但当缓存层被异常流量或热点流量冲击时,常见问题主要有两个:缓存穿透与缓存击穿。这两个问题经常被混用,治理策略也容易配错。本文聚焦实战场景,给出可直接落地的处理方案。
一、缓存穿透是什么
缓存穿透是指:请求的数据在缓存中不存在,在数据库中也不存在。
如果系统不做防护,这类请求每次都会直接打到数据库。
典型场景(穿透)
- 恶意请求随机 ID(如订单号、用户 ID),持续查询不存在的数据。
- 业务参数校验弱,允许大量非法 key 进入查询链路。
- 爬虫流量异常,触发海量无效查询。
风险(击穿)
- 数据库 QPS 被无效请求吞噬。
- 业务正常请求受影响,延迟抖动明显。
- 在峰值期可能引发雪崩式连锁故障。
二、缓存击穿是什么
缓存击穿是指:某个热点 key在高并发下突然过期,大量并发请求同时回源数据库,形成瞬时冲击。
典型场景(击穿)
- 秒杀商品详情、热门活动页配置、高频用户信息等热点数据设置了固定 TTL。
- 同一时间点过期,导致大量请求并发回源。
- 热点 key 重建逻辑耗时较长,窗口期内数据库压力激增。
风险
- 数据库或下游服务瞬时打满。
- 应用线程池阻塞,出现超时和级联失败。
- 热点请求成功率下降,影响核心链路转化。
三、缓存穿透解决方案
1)参数与权限前置校验
- 对 ID 格式、长度、业务范围做强校验,不合法直接返回。
- 对高风险接口加签名校验或鉴权,减少恶意流量直达业务层。
2)布隆过滤器(Bloom Filter)
- 在缓存前增加布隆过滤器,快速判断 key 是否“可能存在”。
- 对明显不存在的 key 直接拦截,避免穿透到数据库。
适用点:高并发读场景、数据集合相对稳定、可接受少量误判(误判存在但实际不存在)。
3)缓存空值(Negative Cache)
- 数据库查询为空时,也写入缓存(如写入
NULL标记,短 TTL)。 - 相同无效请求命中空值缓存,不再反复回源。
注意点:
- TTL 不宜过长,避免影响数据新增后的可见性。
- 对空值命中率做监控,识别异常流量模式。
4)限流与熔断
- 针对不存在 key 的请求增加单接口限流、IP 维度限流。
- 下游压力过高时启用熔断降级,保护核心服务可用性。
四、缓存击穿解决方案
1)热点 key 互斥重建(SingleFlight / 分布式锁)
- 对热点 key 回源重建加互斥:同一时刻仅允许一个请求回源。
- 其他请求等待或返回旧值,避免并发打库。
工程实践:
- 单机可用本地互斥(如
singleflight思路)。 - 分布式场景可用 Redis 锁,但要控制锁超时和兜底逻辑。
2)逻辑过期 + 异步刷新
- 缓存值中存储逻辑过期时间,读到“过期”数据时先返回旧值。
- 后台异步触发刷新,避免同步请求阻塞和回源风暴。
适用点:对“短时间读到旧值”可容忍的业务(如推荐、榜单、详情页)。
3)TTL 随机化
- 给同类 key 的 TTL 加随机抖动(如
baseTTL + random(0, x))。 - 避免大量 key 同时过期造成脉冲式回源。
4)热点预热
- 在活动开始前预加载热点数据到缓存。
- 对已识别热点提前刷新,减少首次请求回源。
五、两类问题的对比速记
| 维度 | 缓存穿透 | 缓存击穿 |
|---|---|---|
| 数据是否存在 | 缓存和数据库都不存在 | 数据存在,但热点 key 过期 |
| 压力来源 | 大量无效请求 | 热点并发请求 |
| 核心手段 | 布隆过滤器、空值缓存、强校验 | 互斥重建、逻辑过期、TTL 随机化 |
六、推荐落地组合(实战)
对于电商/资金等高并发场景,可采用分层策略:
- 入口层:参数校验 + 风险限流。
- 缓存层:空值缓存 + TTL 随机化。
- 热点层:互斥重建(SingleFlight/分布式锁)+ 异步刷新。
- 观测层:监控空值命中率、热点 key 回源次数、数据库慢查询与错误率。
这样可以同时解决“无效请求冲击”和“热点过期风暴”两类问题。
七、结语
缓存问题本质上不是“加个 Redis 就结束”,而是流量模型、数据模型与系统韧性的综合工程。
把缓存穿透和缓存击穿区分清楚,再按业务特征做组合治理,才能在高峰场景下稳定地保护核心链路。