1. 缓存穿透问题概述

1.1 定义

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

核心特征:缓存不命中 + 数据库无记录 = 每次请求都直达数据库。

1.2 产生原因

缓存穿透的根源可归纳为以下三类场景:

原因分类 具体描述 典型示例
业务数据缺失 查询的主键或索引在数据库中本身不存在,缓存自然无法构建 查询一个已删除的商品ID
恶意攻击/爬虫 攻击者构造大量不存在的Key进行高频请求,绕过缓存直接打库 遍历不存在的用户ID(如 -1、0、9999999)
缓存预热不完整 系统上线或缓存过期后,部分冷数据未被加载,导致首次请求穿透 新上线的活动商品未提前写入缓存

1.3 对系统的影响

缓存穿透对系统造成的损害是连锁式的,主要体现在以下两个维度:

  • 数据库压力陡增:正常情况下,缓存层拦截 90% 以上的读请求。穿透发生时,所有无效请求直接打到数据库,数据库连接池迅速耗尽,CPU 和 IO 飙升,严重时导致数据库崩溃。
  • 响应延迟恶化:数据库查询耗时通常是缓存查询的 10~100 倍(缓存约 1~5ms,数据库约 10~100ms)。大量穿透请求导致平均响应时间从毫秒级恶化到秒级,甚至触发上游服务超时重试,形成雪崩效应。
风险量化:假设缓存 QPS 为 10,000,其中 1% 为穿透请求(100 QPS)。若数据库单次查询耗时 50ms,则数据库额外承受 100 QPS × 50ms = 5,000ms/s 的负载,相当于多消耗 5 个数据库连接线程。若攻击流量放大至 10%,数据库将直接过载。

1.4 穿透流程示意图

下图展示了正常请求与穿透请求的路径差异:

缓存穿透请求 vs 正常请求流程对比 正常请求(缓存命中) 客户端请求 缓存命中 返回数据 客户端响应 穿透请求(缓存未命中) 客户端请求 缓存未命中 查询数据库 数据库无记录 返回空/错误 正常请求路径 客户端 → 缓存 → 返回 数据库无压力,响应快 穿透路径:客户端 → 缓存 → 数据库 → 空结果

1.5 穿透与相关概念辨析

为避免概念混淆,下表区分了缓存穿透与另外两种常见缓存异常:

异常类型 触发条件 影响范围 典型后果
缓存穿透 数据不存在,缓存永远无法命中 单个无效Key 数据库直接承受无效查询压力
缓存击穿 热点Key过期,大量并发请求同时穿透 单个热点Key 数据库瞬间被高并发打垮
缓存雪崩 大量Key同时过期或缓存节点宕机 大面积Key失效 数据库被海量请求压垮,系统级故障