4. 缓存穿透问题详解:定义、产生原因与数据库压力影响
缓存穿透是分布式缓存系统中危害最严重的一类故障模式。它指查询一个根本不存在的数据时,由于缓存层无法命中(缓存中没有该 key),请求直接穿透缓存层,每次都落到后端数据库上。当这类请求量级足够大时,数据库连接池会被迅速耗尽,导致正常查询也超时或失败,最终引发级联雪崩。
核心定义:缓存穿透 = 查询不存在的数据 → 缓存永远无法命中 → 请求直达数据库 → 数据库压力剧增。
4.1 缓存穿透的产生原因
缓存穿透并非单一场景所致,从攻击行为到业务设计缺陷都可能触发。下表归纳了最常见的三类成因:
| 成因分类 | 典型场景 | 请求特征 | 危害等级 |
|---|---|---|---|
| 恶意攻击 | 遍历不存在的用户ID、伪造订单号、扫描无效商品SKU | 高频、随机、无规律 | ★★★★★ |
| 空数据查询 | 查询已删除的记录、查询未生成的报表、查询过期活动 | 偶发但持续存在 | ★★★☆☆ |
| 缓存与数据库状态不一致 | 数据已删除但缓存未清除、缓存过期后数据被物理删除 | 间歇性、与业务操作耦合 | ★★☆☆☆ |
4.2 恶意攻击:穿透的“放大器”
恶意攻击是缓存穿透最危险的诱因。攻击者利用业务规则中的可枚举参数(如自增ID、时间戳、哈希值),构造大量不存在但格式合法的请求。由于这些 key 在缓存中永远不存在,每次请求都直接穿透到数据库层。
- 特征一:请求参数随机性强,无法通过简单限流拦截。
- 特征二:QPS 可瞬间达到正常值的 10~100 倍,数据库连接池秒级打满。
- 特征三:攻击者常使用分布式僵尸网络,源 IP 分散,传统 IP 黑名单失效。
实战案例:某电商平台在促销期间遭遇恶意攻击,攻击者遍历不存在的商品 ID(从 1000000 到 2000000),每秒产生约 5 万次穿透查询。数据库 CPU 从 20% 飙升至 98%,正常用户请求超时率达 73%。事后分析发现,缓存命中率从 95% 骤降至 12%。
4.3 空数据查询:业务设计中的“隐形漏洞”
空数据查询往往被开发团队忽视,但其累积效应同样不可小觑。当业务逻辑允许查询“可能不存在”的数据时,每一次空查询都会穿透缓存。
常见的空数据查询场景包括:
- 查询已逻辑删除的记录:用户访问一个已下架的商品详情页,数据库返回空,缓存未写入。
- 查询未生成的报表:定时任务尚未执行,用户提前访问报表接口,每次穿透到数据库。
- 查询过期活动:活动已结束但前端未及时更新入口,用户持续点击失效链接。
与恶意攻击不同,空数据查询的 QPS 通常较低,但持续时间长、覆盖范围广,在微服务架构中可能同时穿透多个数据库实例。
4.4 对数据库的压力影响:量化分析
缓存穿透对数据库的压力可以用一个简单的公式量化:
数据库实际 QPS = 穿透率 × 总请求 QPS
其中:
- 穿透率 = 未命中缓存的请求比例(正常情况 < 5%)
- 穿透攻击时,穿透率 ≈ 100%
假设一个正常业务的缓存命中率为 95%,总请求 QPS 为 10,000:
- 正常情况:数据库 QPS = 10,000 × 5% = 500 QPS(数据库可承受)
- 穿透攻击时:数据库 QPS = 10,000 × 100% = 10,000 QPS(数据库直接过载)
数据库在承受 10,000 QPS 时,通常会出现以下连锁反应:
| 压力阶段 | 数据库表现 | 对业务的影响 |
|---|---|---|
| 第一阶段(0~5秒) | 连接池满,新请求排队 | 部分接口响应时间从 10ms 升至 500ms |
| 第二阶段(5~15秒) | 慢查询堆积,CPU 飙升 | 超时率上升至 30%,开始影响正常用户 |
| 第三阶段(15秒后) | 数据库连接被强制断开,主从同步延迟 | 服务大面积不可用,触发熔断降级 |
关键指标:当数据库 QPS 超过其最大承载能力的 2 倍时,响应时间会呈指数级增长,而非线性增长。这是数据库连接池和锁竞争共同作用的结果。
4.5 缓存穿透的完整流程图示
下图展示了缓存穿透的完整请求链路,以及正常请求与穿透请求的路径差异:
4.6 穿透压力的“放大效应”
缓存穿透对数据库的压力并非简单的 1:1 映射,而是存在明显的放大效应:
- 连接池放大:每个穿透请求占用一个数据库连接,连接池满后新请求排队,响应时间成倍增加。
- 锁竞争放大:数据库行锁、表锁在并发穿透时竞争加剧,导致正常查询也被阻塞。
- IO 放大:穿透请求通常涉及全表扫描或索引回表,磁盘 IO 压力远高于正常查询。
- 主从延迟放大:大量写操作(如日志记录)与穿透读操作争抢 IO,导致主从同步延迟。
经验数据:在 MySQL 8.0 环境中,1,000 QPS 的穿透请求(全表扫描)产生的数据库 CPU 消耗,相当于 10,000 QPS 的正常索引查询。穿透请求的资源消耗是正常请求的 5~10 倍。
4.7 穿透与雪崩的关联
缓存穿透往往是缓存雪崩的前奏。当数据库因穿透压力过载后,即使后续请求是正常数据,也无法从数据库获取结果,导致缓存无法回填。此时,所有请求都变成穿透请求,形成正反馈循环:
穿透请求 → 数据库过载 → 正常数据也无法返回 → 缓存无法回填 → 更多穿透请求 → 数据库崩溃
这种级联效应在微服务架构中传播更快,因为一个服务的数据库过载会通过 RPC 调用链影响到上游服务,最终导致整个调用链路熔断。