2. 缓存穿透原理
2.1 缓存穿透的定义
缓存穿透(Cache Penetration)是指查询一个根本不存在的数据时,缓存层和数据库层都无法命中该数据。由于缓存层没有存储该数据的副本,每次请求都会绕过缓存,直接穿透到数据库层执行查询。当大量并发请求查询同一个不存在的 key 或一组不存在的 key 时,数据库会承受巨大的查询压力,甚至可能导致数据库服务崩溃。
核心特征:缓存层与数据库层均无数据 → 请求绕过缓存 → 直接压向数据库。
2.2 发生场景分析
缓存穿透并非偶发故障,而是由业务逻辑或攻击行为引发的系统性风险。以下为最常见的三类发生场景:
| 场景类别 | 典型示例 | 请求特征 | 危害等级 |
|---|---|---|---|
| 业务正常查询 | 用户查询已下架商品、已注销账号、过期订单 | 少量、偶发、符合业务预期 | 低 |
| 恶意攻击 | 遍历不存在的 ID(如 -1、0、9999999) | 大量、高频、参数异常 | 高 |
| 缓存与数据库数据不一致 | 缓存淘汰后数据库记录被物理删除 | 突发、集中、难以预测 | 中 |
注意:恶意攻击场景下,攻击者往往利用业务 ID 生成规律(如自增主键)构造大量无效请求,使缓存层完全失效,数据库成为唯一瓶颈。
2.3 对数据库的压力影响
缓存穿透对数据库的压力影响可以通过以下量化指标来理解。假设系统正常状态下缓存命中率为 95%,数据库每秒处理能力为 1000 QPS:
- 正常状态:1000 次请求 → 缓存命中 950 次 → 数据库仅处理 50 次查询 → 数据库负载 5%
- 穿透攻击状态:1000 次请求 → 缓存命中 0 次 → 数据库处理 1000 次查询 → 数据库负载 100%
- 压力放大效应:数据库 QPS 瞬间增长 20 倍,连接池耗尽,响应超时,引发级联故障
经验数据:实际生产环境中,一次针对不存在的商品 ID 的穿透攻击,可在 30 秒内将数据库 QPS 从 200 推高至 8000+,导致数据库连接池满、慢查询堆积、主从延迟飙升。
2.4 缓存穿透流程示意图
下图展示了正常查询与缓存穿透查询的路径差异,清晰呈现穿透发生时请求如何绕过缓存直接冲击数据库:
2.5 穿透压力传导链
缓存穿透的压力并非孤立事件,而是沿着系统调用链逐级传导,形成典型的压力放大效应:
- 入口层:大量无效请求涌入 API 网关或负载均衡器
- 应用层:业务逻辑层反复查询缓存,每次均返回 null
- 缓存层:缓存未命中,请求穿透至数据库访问层
- 数据库层:数据库执行全表扫描或索引查找,返回空结果集
- 级联效应:数据库连接池耗尽 → 正常查询超时 → 应用线程阻塞 → 服务雪崩
关键结论:缓存穿透的本质是缓存层保护失效。当缓存无法拦截无效查询时,数据库成为唯一的兜底层,而数据库的设计目标并非应对高频空查询,因此极易成为系统瓶颈。
2.6 穿透与击穿、雪崩的对比
为帮助学员建立清晰的概念边界,下表对比了缓存穿透与另外两种常见缓存故障:
| 故障类型 | 触发条件 | 缓存状态 | 数据库影响 | 典型修复手段 |
|---|---|---|---|---|
| 缓存穿透 | 查询不存在的数据 | 始终未命中 | 大量空查询压力 | 布隆过滤器、空值缓存 |
| 缓存击穿 | 热点 key 过期 | 瞬间未命中 | 单 key 高并发回源 | 互斥锁、逻辑过期 |
| 缓存雪崩 | 大量 key 同时过期 / 缓存宕机 | 大面积未命中 | 海量回源压力 | 过期时间随机化、缓存高可用 |
学习提示:穿透、击穿、雪崩是缓存保护的三类核心问题。穿透关注的是“数据不存在”,击穿关注的是“热点过期”,雪崩关注的是“大规模失效”。理解三者的区别是设计保护算法的前提。