4. 缓存穿透原理:请求绕过缓存直接查询数据库的成因与危害

缓存穿透是分布式缓存系统中破坏力最强的失效模式之一。当客户端请求的数据在缓存中不存在,且数据库中也不存在该数据时,每次请求都会绕过缓存直接穿透到数据库层。由于缓存层无法对该类请求进行拦截,大量并发请求会瞬间压向后端存储,导致数据库连接池耗尽、慢查询堆积,甚至引发级联雪崩。

4.1 缓存穿透的成因分析

缓存穿透并非缓存失效的常规场景,其核心成因可归纳为以下三类:

成因类别 具体描述 典型场景
恶意攻击 攻击者构造大量不存在的主键 ID(如负数、超大整数、随机字符串)发起请求,缓存层永远无法命中,请求直接穿透至数据库。 爬虫遍历不存在的商品 ID;刷接口攻击
业务逻辑缺陷 上游服务未对请求参数做合法性校验,导致非法 key 进入缓存查询流程,缓存 miss 后直接查询数据库。 前端传入空值或格式错误的用户 ID
缓存与数据库数据不一致 数据库中被删除的数据,缓存中对应的 key 未被及时清理,后续请求查缓存 miss,查数据库也返回空,形成穿透。 后台删除商品后未同步删除缓存 key
关键判断标准: 缓存穿透与缓存击穿的本质区别在于——击穿是缓存中存在的热点 key 过期,而穿透是缓存中根本不存在该 key,且数据库中也无对应记录。

4.2 缓存穿透的危害链

一次穿透请求的危害有限,但高并发场景下的穿透会形成以下危害链:

  1. 数据库连接耗尽: 应用层线程池中的每个线程都阻塞等待数据库查询,连接池快速被占满。
  2. 慢查询堆积: 数据库对不存在数据的查询无法利用索引覆盖,全表扫描导致 CPU 和 IO 飙升。
  3. 服务响应超时: 上游调用方因等待数据库响应而超时,触发重试机制,进一步放大流量。
  4. 级联雪崩: 数据库负载过高导致正常请求也变慢,缓存层因等待数据库响应而积压,最终整个服务集群不可用。
生产事故警示: 某电商平台在促销期间遭遇恶意攻击,攻击者遍历不存在的 SKU ID(从 1 到 10^8),导致数据库每秒承受超过 20 万次无效查询,主库 CPU 使用率瞬间飙升至 100%,核心商品查询接口超时率达 95%,最终触发全站降级。

4.3 缓存穿透的请求流程(SVG 架构图)

下图展示了正常请求与穿透请求在缓存层和数据库层的路径差异:

缓存穿透请求流程 vs 正常请求流程 客户端请求 Redis 缓存层 数据库层 ① 查询缓存 ② 缓存命中 恶意请求 Redis 缓存层 数据库层 ① 查询缓存 ② 缓存 Miss ③ 穿透查询 返回空结果 ④ 不缓存空值 危害:每次穿透都产生一次数据库查询,高并发下数据库连接池瞬间耗尽 缓存层形同虚设,请求绕过缓存直接攻击数据库

4.4 缓存穿透的量化影响

以下表格对比了正常请求与穿透请求在资源消耗上的差异:

指标维度 正常请求(缓存命中) 穿透请求(缓存 Miss + 数据库空) 性能差距
响应延迟 1~5 ms 50~200 ms(数据库查询) 10~40 倍
数据库连接占用 0 1 个连接 / 请求 无限放大
数据库 CPU 消耗 0 全表扫描,CPU 密集 极高
缓存层负载 正常读写 大量 Miss,无缓存写入 缓存层空转
系统吞吐量 10,000+ QPS 500~1,000 QPS(受限于数据库) 下降 90%+

4.5 缓存穿透与缓存击穿、缓存雪崩的对比

为了帮助理解缓存穿透在整个缓存失效体系中的位置,下表对比了三种常见失效模式:

失效模式 触发条件 影响范围 典型应对策略
缓存穿透 请求的数据在缓存和数据库中都不存在 单个 key 或一组不存在的 key 布隆过滤器、缓存空对象、参数校验
缓存击穿 热点 key 在缓存中过期,大量并发请求同时访问 单个热点 key 互斥锁、逻辑过期、永不过期
缓存雪崩 大量 key 同时过期或缓存节点宕机 整个缓存层或大量 key 过期时间随机化、缓存集群高可用、限流降级
设计启示: 缓存穿透是所有缓存失效模式中最容易被忽视的一种,因为它不依赖缓存本身的过期机制,而是依赖业务数据的完整性。在搜索服务中,用户输入的搜索词可能包含大量无意义或恶意构造的词汇,缓存穿透的防御必须前置到接口层。