2. 缓存基础:缓存的定义、缓存命中率、缓存穿透、缓存雪崩、缓存击穿

在构建高性能 API 网关时,缓存是降低后端数据库负载、缩短响应延迟的核心手段。然而,缓存并非银弹——错误的使用方式会导致系统雪崩或数据不一致。本节从缓存的基本定义出发,逐步剖析命中率、穿透、雪崩、击穿四大关键概念,为后续的网关缓存与 DB 一致性校验实践奠定理论基础。

2.1 缓存的定义与工作原理

缓存(Cache)是一种将数据临时存储在高速存储介质(如内存)中的技术,目的是加速后续相同数据的访问。在 API 网关场景中,缓存通常位于客户端与后端服务之间,用于存储频繁查询的响应结果。

核心公式: 缓存加速比 = 原始访问延迟 / 缓存访问延迟。理想情况下,缓存访问延迟应比 DB 访问低 1~3 个数量级。

缓存系统的基本工作流程包含三个步骤:

  1. 查询缓存: 请求到达时,网关首先检查缓存中是否存在目标键(Key)。
  2. 缓存命中: 若存在,直接返回缓存值,跳过后端 DB。
  3. 缓存未命中: 若不存在,回源到 DB 查询,将结果写入缓存后再返回。
缓存基本工作流程 客户端 API 网关 缓存层 (Redis) 数据库 (DB) ① 请求 ② 查询 ③ 命中 → 直接返回 ④ 未命中 → 回源 DB ⑤ 返回结果 ⑥ 写入缓存 ⑦ 响应 说明:③ 与 ④ 为互斥路径,缓存命中时跳过 DB 回源,大幅降低延迟。

2.2 缓存命中率

缓存命中率(Cache Hit Ratio)是衡量缓存效率的核心指标,定义为缓存命中的请求数占总请求数的百分比。

指标 公式 理想范围 说明
命中率 命中次数 / (命中次数 + 未命中次数) × 100% ≥ 90% 命中率越高,DB 压力越小
未命中率 1 - 命中率 ≤ 10% 未命中率过高需排查缓存策略
字节命中率 缓存提供的数据量 / 总请求数据量 ≥ 80% 适用于大对象缓存场景
实践建议: 在 API 网关中,应针对每个路由(Route)分别统计命中率。若某路由命中率持续低于 70%,应考虑调整 TTL、预热策略或检查 Key 设计是否合理。

2.3 缓存穿透

缓存穿透 指请求查询一个缓存和数据库中都不存在的数据。由于缓存未命中,每次请求都会穿透到 DB,导致 DB 承受大量无效查询,严重时可能拖垮数据库。

典型场景:恶意攻击者频繁请求不存在的用户 ID(如负数 ID 或随机 UUID)。

解决方案对比

方案 原理 优点 缺点
缓存空对象 将 null 或特殊标记写入缓存,设置短 TTL(如 30s) 实现简单,通用性强 占用缓存空间,短时间大量空 Key 仍可能冲击 DB
布隆过滤器 在网关层维护一个位图结构,快速判断 Key 是否存在 空间效率极高,不存在误判为存在 存在误判为不存在(假阳性),需定期重建
参数校验 + 限流 在网关层拦截非法参数,对异常请求直接拒绝 从源头阻断无效请求 无法防御合法参数但数据不存在的情况

2.4 缓存雪崩

缓存雪崩 指大量缓存 Key 在同一时间过期失效,或缓存节点宕机,导致所有请求瞬间涌入 DB,造成数据库压力激增甚至崩溃。

雪崩与穿透的区别:穿透针对不存在的数据,雪崩针对存在但已过期的数据。

预防策略

  • 均匀过期: 在基础 TTL 上增加随机偏移量(如 ±10%),避免大量 Key 同时过期。
  • 多级缓存: 本地缓存(如 Caffeine)+ 分布式缓存(如 Redis)分层部署,本地缓存失效后仍可命中 Redis。
  • 缓存预热: 系统启动或大促前,提前将热点数据加载到缓存中。
  • 限流降级: 网关层配置熔断和限流,当 DB 负载超过阈值时直接返回降级响应。
注意: 缓存雪崩的恢复比穿透更困难,因为雪崩时 DB 可能已经处于过载状态,需要配合熔断和渐进式恢复策略。

2.5 缓存击穿

缓存击穿 指一个热点 Key 在缓存过期的瞬间,大量并发请求同时访问该 Key,导致所有请求都穿透到 DB。击穿是雪崩的一种特例——雪崩是大量 Key 同时失效,击穿是单个热点 Key 失效。

解决方案对比

方案 原理 适用场景 注意事项
互斥锁(Mutex) 第一个请求获取锁并回源 DB,其他请求等待或快速失败 并发量极高,数据一致性要求严格 需防止死锁,锁超时时间应合理设置
逻辑过期 缓存永不过期,但数据内嵌逻辑过期时间,异步线程更新 允许短暂数据不一致 需额外维护异步更新线程池
二级缓存 热点 Key 在本地缓存和 Redis 中各存一份,本地缓存 TTL 更短 读多写少,对一致性要求不高 本地缓存占用 JVM 内存
缓存穿透 / 雪崩 / 击穿 对比 缓存穿透 特征 数据在缓存和 DB 中 都不存在 每次请求都穿透到 DB 解决方案 缓存空对象 / 布隆过滤器 参数校验 + 限流 缓存雪崩 特征 大量 Key 同时过期 或缓存节点宕机 所有请求涌入 DB 解决方案 均匀过期(TTL + 随机偏移) 多级缓存 / 限流降级 缓存击穿 特征 单个热点 Key 过期 大量并发请求同时访问 雪崩的特例 解决方案 互斥锁 / 逻辑过期 二级缓存 三者核心区别 穿透:数据不存在 雪崩:大量 Key 同时失效 击穿:单个热点 Key 失效 DB 承受无效查询 DB 承受瞬时洪峰 DB 承受并发穿透

2.6 三种异常对比总结

维度 缓存穿透 缓存雪崩 缓存击穿
根本原因 查询不存在的数据 大量 Key 同时过期 / 节点宕机 热点 Key 过期 + 高并发
影响范围 单个 Key 或少量 Key 全局或大面积 单个热点 Key
DB 压力特征 持续低效查询 瞬时洪峰 瞬时高并发穿透
首选方案 布隆过滤器 均匀过期 + 多级缓存 互斥锁
网关层干预 参数校验 + 限流 限流 + 熔断降级 分布式锁 + 本地缓存
网关实践要点: 在 OpenAPI 网关中,建议对每个路由配置独立的缓存策略。对于高频查询接口(如用户信息、商品详情),优先使用“缓存空对象 + 布隆过滤器”组合防御穿透;对于大促场景,提前执行缓存预热并启用二级缓存,防止雪崩和击穿。