2. 缓存穿透的典型场景:恶意攻击场景、空数据查询场景、热点Key失效场景分析

缓存穿透是指查询一个一定不存在的数据,由于缓存层不命中,请求直接穿透到后端存储层(如数据库),导致存储层承受巨大压力。理解其典型场景是设计穿透保护算法的前提。本章从三个核心维度展开分析:恶意攻击、空数据查询、热点Key失效。

2.1 场景对比总览

下表从触发原因、请求特征、影响范围三个维度对比三种典型穿透场景,帮助建立全局认知。

场景类型 触发原因 请求特征 影响范围
恶意攻击场景 攻击者利用系统漏洞,构造大量不存在的Key Key随机、高频、无规律 全局性,可能拖垮整个数据库
空数据查询场景 业务逻辑导致查询不存在的数据(如非法ID) Key可预测、低频但持续 局部性,影响特定业务接口
热点Key失效场景 热点Key在缓存中过期,大量并发请求同时回源 Key固定、瞬时高并发 局部性,但冲击峰值极高

2.2 恶意攻击场景

恶意攻击是缓存穿透最危险的场景。攻击者通常通过爬虫、脚本或分布式僵尸网络,向系统发送大量不存在于缓存和数据库中的Key。例如,一个电商系统的商品详情接口,攻击者遍历不存在的商品ID(如负数、超长数字、UUID格式字符串),导致每次请求都穿透到数据库。

典型攻击特征:请求Key的分布呈现均匀随机或完全无序,与正常用户请求的幂律分布(Zipf分布)明显不同。监控系统可通过Key的熵值或请求分布曲线快速识别。

攻击流程可抽象为以下步骤:

  1. 构造无效Key:攻击者生成大量不存在的Key(如随机32位字符串)。
  2. 绕过缓存:缓存层未命中,请求直接转发到数据库。
  3. 数据库空查询:数据库执行查询,返回空结果集。
  4. 资源耗尽:大量空查询耗尽数据库连接池、CPU和IO,导致正常请求超时。
治理要点:布隆过滤器(Bloom Filter)是应对恶意攻击的首选方案。在缓存层前置布隆过滤器,将所有可能存在的数据Key预加载到过滤器中,对于不存在的数据直接拦截,避免穿透到数据库。

2.3 空数据查询场景

空数据查询场景通常由业务逻辑缺陷或用户输入校验不严导致。例如,用户查询一个已被逻辑删除的订单、查询一个不存在的用户ID、或者前端传入非法枚举值。与恶意攻击不同,空数据查询的Key往往具有可预测性(如连续ID、固定格式),且请求频率相对较低。

该场景的核心问题在于:缓存层没有存储“空”的语义。当数据库返回空结果时,缓存层默认不缓存该Key,导致下一次相同Key的查询再次穿透。

对比维度 恶意攻击场景 空数据查询场景
Key来源 随机、无规律 可预测、有业务含义
请求频率 极高(万级QPS以上) 中低(百级QPS以下)
治理策略 布隆过滤器 + 限流 缓存空对象 + 短TTL
副作用 内存占用可控(过滤器固定大小) 缓存空间浪费(需设置过期时间)
最佳实践:对于空数据查询,采用“缓存空对象”策略。将数据库返回的null或空集合缓存到Redis中,并设置较短的过期时间(如30-60秒)。这样,相同Key的重复查询在TTL内直接返回空结果,避免穿透。同时配合Key命名规范(如添加“:empty”后缀),便于监控和清理。

2.4 热点Key失效场景

热点Key失效是缓存穿透中最隐蔽且破坏力最强的场景。当某个热点数据(如秒杀商品、热搜新闻)的缓存Key过期时,大量并发请求在同一时刻回源到数据库,瞬间打穿数据库连接。这种现象也被称为“缓存击穿”(Cache Breakdown),是穿透的一种特殊形式。

热点Key失效的典型特征:

  • Key唯一:失效的Key通常只有一个或少数几个。
  • 并发极高:请求集中在Key失效后的极短时间窗口内(毫秒级)。
  • 数据库压力瞬时尖峰:数据库QPS从正常值瞬间飙升数十倍甚至百倍。
治理要点:热点Key失效的治理核心是“避免同一时刻大量请求同时回源”。常用方案包括:
1. 互斥锁(Mutex Key):只允许一个线程去数据库加载数据,其他线程等待或快速失败。
2. 逻辑过期:缓存Key不设置物理过期时间,而是存储一个逻辑过期时间字段,由后台线程异步刷新。
3. 二级缓存:本地缓存(如Caffeine)配合分布式缓存,本地缓存作为第一道防线。

2.5 三种场景的穿透路径对比(SVG架构图)

下图从请求路径角度对比三种穿透场景的流量走向,帮助理解不同场景下缓存层、过滤层、数据库层的压力分布。

缓存穿透三种典型场景请求路径对比 缓存穿透三种典型场景请求路径对比 恶意攻击 空数据查询 热点Key失效 客户端请求层 缓存层(Redis / Memcached) Key不存在 Key不存在 Key过期 过滤/拦截层(布隆过滤器 / 限流 / 互斥锁) 数据库层(MySQL / PostgreSQL) 压力:极高(万级QPS) 压力:中低(百级QPS) 压力:瞬时尖峰(千级QPS) 恶意攻击治理 布隆过滤器 + 限流降级 空数据查询治理 缓存空对象 + 短TTL 热点Key失效治理 互斥锁 / 逻辑过期 / 二级缓存

2.6 场景识别与监控指标

在实际生产环境中,快速识别穿透场景是治理的第一步。下表列出三种场景对应的关键监控指标和告警阈值建议。

监控指标 恶意攻击场景 空数据查询场景 热点Key失效场景
缓存命中率 断崖式下降(从95%降至10%以下) 缓慢下降(每周下降1-2%) 瞬时抖动(秒级下降后恢复)
数据库QPS 线性飙升,与请求量正相关 平稳上升,与空Key数量相关 瞬时尖峰,持续1-5秒后回落
Key访问分布 均匀分布(熵值接近最大值) 集中在特定前缀或ID范围 单个Key访问量占比超过50%
告警阈值建议 缓存命中率 < 50% 且数据库QPS > 基线3倍 空Key查询占比 > 20% 持续5分钟 单个Key QPS > 1000 且缓存未命中
监控工具推荐:使用Redis的INFO commandstats命令监控get/set命令频率;使用Prometheus + Grafana构建缓存命中率仪表盘;对于热点Key,可利用Redis 4.0+的hotkeys参数或阿里云Redis的热点Key检测功能。

2.7 场景治理优先级矩阵

根据影响范围和治理成本,三种场景的治理优先级不同。下图以矩阵形式展示,帮助团队制定治理路线图。

缓存穿透场景治理优先级矩阵 缓存穿透场景治理优先级矩阵 高 影响范围 低 低 治理成本 高 优先治理 重点规划 快速修复 持续优化 恶意攻击场景 影响大 · 成本低 热点Key失效 影响大 · 成本高 空数据查询 影响小 · 成本低 其他穿透场景 影响小 · 成本高

根据优先级矩阵,建议的治理路线为:

  • 第一阶段(优先治理):部署布隆过滤器防御恶意攻击,这是投入产出比最高的方案。
  • 第二阶段(快速修复):对空数据查询场景实施缓存空对象策略,修复业务逻辑漏洞。
  • 第三阶段(重点规划):针对热点Key失效场景,设计互斥锁或逻辑过期方案,需要结合业务特点定制。
核心结论:三种穿透场景的治理策略并非互斥,实际生产环境往往是多种场景叠加。例如,恶意攻击可能同时利用空数据查询和热点Key失效的漏洞。因此,推荐采用“分层防御”架构:第一层布隆过滤器(拦截不存在Key)、第二层缓存空对象(处理空数据)、第三层互斥锁/逻辑过期(保护热点Key),形成纵深防御体系。