1. 缓存穿透概述

1.1 什么是缓存穿透

缓存穿透(Cache Penetration)是指客户端请求的数据在缓存层和数据库层中均不存在,导致每次请求都直接穿透缓存层,直达后端数据库。由于缓存层无法命中,所有请求压力全部落在数据库上,形成“缓存失效 → 数据库直击”的恶性循环。

核心定义:缓存穿透 = 缓存未命中 + 数据库无记录 → 请求绕过缓存直接攻击数据库。

与缓存击穿(热点 key 过期)和缓存雪崩(大量 key 同时过期)不同,穿透问题的本质是数据本身不存在,而非缓存数据失效。因此,即使缓存服务完全正常,穿透依然会发生。

缓存穿透 vs 正常请求流程对比 正常请求流程 客户端请求 缓存命中 返回数据 ✅ 数据库无压力 缓存穿透流程 客户端请求 缓存未命中 查询数据库 无记录返回 ❌ 数据库被直击 穿透本质:缓存层形同虚设,每次请求都穿透到数据库,且数据库返回空结果

1.2 穿透对系统的危害

缓存穿透并非“小概率事件”,一旦被恶意利用或触发高频空查询,会对系统造成连锁破坏。下表总结了穿透在不同层面的危害表现:

危害维度 具体表现 严重程度
数据库连接耗尽 每次穿透都占用一个数据库连接,连接池迅速枯竭,正常请求也被阻塞 ★★★★★
数据库 CPU/IO 飙升 大量空查询导致数据库执行全表扫描或索引无效扫描,CPU 和磁盘 IO 瞬间打满 ★★★★★
响应延迟雪崩 数据库变慢后,所有依赖该数据库的接口响应时间从毫秒级退化到秒级甚至超时 ★★★★☆
缓存层资源浪费 缓存服务器虽然未命中,但仍消耗网络带宽和连接资源,影响正常缓存查询 ★★★☆☆
业务数据污染 穿透导致大量空结果被误写入缓存(若代码逻辑不当),挤占正常缓存空间 ★★★☆☆
系统级连锁故障 数据库宕机 → 应用层重试风暴 → 负载均衡过载 → 整个服务集群不可用 ★★★★★
⚠️ 真实案例警示:某电商平台在促销期间,爬虫批量请求不存在的商品 ID(如负数 ID、超长 ID),导致数据库每秒承受超过 20 万次空查询,连接池 3 秒内耗尽,核心商品查询接口完全瘫痪 15 分钟,直接损失超百万。

1.3 穿透发生的典型场景

缓存穿透并非只出现在恶意攻击中,正常业务逻辑同样可能触发。以下是生产环境中最常见的六类穿透场景:

  1. 恶意攻击 / 爬虫扫描
    攻击者构造大量不存在的 key(如负数 ID、随机字符串、超长参数)发起请求,利用缓存空挡耗尽数据库资源。
  2. 业务查询不存在的数据
    用户查询已删除的商品、已注销的账号、过期的订单等,缓存和数据库均无记录。
  3. 批量导入 / 数据同步间隙
    数据尚未同步到缓存或数据库时,前端已经发起查询请求,导致穿透。
  4. 缓存预热不完整
    新上线服务或重启后,缓存中只有部分热点数据,大量非热点 key 直接穿透。
  5. 分页 / 列表查询空结果
    查询条件过于严格导致数据库返回空列表,且该空结果未被缓存。
  6. 参数校验缺失
    前端或网关未对参数做合法性校验,非法参数(如空值、越界值)直接穿透到后端。
缓存穿透典型场景分类 缓存穿透典型场景分类 缓存穿透 恶意攻击 / 爬虫扫描 参数校验缺失 查询不存在的数据 数据同步间隙 缓存预热不完整 / 空结果

1.4 穿透与击穿、雪崩的区别

很多开发者容易混淆缓存穿透、缓存击穿和缓存雪崩。下表从触发原因、影响范围和典型特征三个维度进行对比:

概念 触发原因 影响范围 典型特征
缓存穿透 请求的数据在缓存和数据库中都不存在 单个 key 或批量不存在的 key 缓存未命中 + 数据库空结果
缓存击穿 热点 key 在缓存中过期失效 单个热点 key 高并发瞬间涌入数据库
缓存雪崩 大量 key 同时过期或缓存节点宕机 大面积 key 或整个缓存集群 数据库瞬间被海量请求淹没