2. 缓存基础回顾:缓存的定义、缓存层级与常见策略
在深入 OpenAPI 场景的缓存一致性之前,有必要先厘清缓存的核心概念。缓存并非简单的“存一下数据”,而是一种通过空间换时间、减少昂贵 I/O 或计算开销的系统性手段。本节从定义出发,逐步拆解缓存层级与淘汰策略,为后续的穿透保护与一致性设计奠定基础。
2.1 缓存的定义与核心价值
缓存(Cache)是位于原始数据源与请求方之间的临时存储层,用于保存频繁访问的数据副本。当请求到达时,若缓存命中则直接返回,避免重复查询数据库、远程服务或执行复杂计算。
| 维度 | 说明 |
|---|---|
| 核心目标 | 降低访问延迟、减少后端负载、提升系统吞吐量 |
| 典型场景 | 热点数据查询、会话状态、API 响应缓存、配置信息 |
| 代价 | 引入数据不一致风险、增加内存/存储开销、需要失效策略 |
关键认知:缓存不是万能药。在 OpenAPI 网关或微服务架构中,缓存策略必须与业务一致性要求对齐。读多写少、容忍短暂不一致的场景最适合引入缓存。
2.2 缓存层级:本地缓存与分布式缓存
根据缓存数据的存储位置与共享范围,缓存可分为两大层级。理解二者的差异是设计分层缓存架构的前提。
2.2.1 本地缓存(Local Cache)
数据存储在应用进程内部的内存中,如 Java 的 Caffeine、Guava Cache,或 Go 的 freecache。访问速度极快(纳秒级),但无法跨进程共享,且受限于单机内存容量。
- 优点:零网络开销、延迟最低、实现简单。
- 缺点:数据孤立、重启丢失、各节点缓存不一致。
- 适用:配置信息、静态元数据、单机限流计数。
2.2.2 分布式缓存(Distributed Cache)
数据存储在独立的缓存服务中,如 Redis、Memcached。所有应用实例共享同一缓存池,支持更大容量和跨节点一致性。
- 优点:容量可扩展、数据共享、支持持久化与集群。
- 缺点:网络延迟(毫秒级)、序列化开销、依赖中间件稳定性。
- 适用:用户会话、全局热点数据、API 响应聚合。
架构建议:在 OpenAPI 网关层,通常采用“本地缓存 + 分布式缓存”两级架构。本地缓存过滤高频重复请求,分布式缓存作为共享后备,兼顾速度与一致性。
2.3 常见缓存策略
缓存策略决定了数据何时被写入、何时被淘汰。错误的策略会导致缓存击穿、内存溢出或数据长期不一致。以下是最核心的两种策略。
2.3.1 LRU(Least Recently Used)
LRU 基于“最近访问时间”淘汰数据:当缓存容量满时,移除最久未被访问的条目。实现上通常采用哈希表 + 双向链表,保证读写时间复杂度为 O(1)。
- 适用场景:访问模式符合局部性原理,近期访问的数据未来更可能被再次访问。
- 变体:LRU-K(记录最近 K 次访问)、Segmented LRU(分段 LRU,如 Caffeine 的 W-TinyLFU)。
- 注意:全表扫描或突发批量请求可能污染缓存,导致热点数据被意外淘汰。
2.3.2 TTL(Time To Live)
TTL 为每个缓存条目设置一个过期时间,到期后自动失效。这是保证缓存与数据源最终一致性的最直接手段。
| TTL 类型 | 说明 | 典型值 |
|---|---|---|
| 固定 TTL | 所有条目使用相同的过期时长 | 60s、300s |
| 随机 TTL | 在基础 TTL 上增加随机偏移,防止缓存雪崩 | 60s ± 10s |
| 动态 TTL | 根据数据热度或业务窗口动态调整过期时间 | 热点数据 30s,冷数据 600s |
常见陷阱:仅依赖 TTL 无法解决缓存与数据库的强一致性问题。在 TTL 窗口内,如果数据库已更新但缓存未失效,就会返回脏数据。对于写频繁的场景,需要配合主动失效或 CDC(Change Data Capture)机制。
2.4 策略组合与选型建议
单一策略往往无法满足复杂场景。下表总结了常见组合方式及其适用场景。
| 组合方式 | 工作机制 | 推荐场景 |
|---|---|---|
| LRU + 固定 TTL | 容量淘汰 + 时间过期双重保障 | 通用热点缓存,如用户信息、商品详情 |
| LRU + 随机 TTL | 避免大量缓存同时过期导致雪崩 | 高并发读场景,如秒杀商品列表 |
| 仅 TTL(无容量限制) | 只依赖时间过期,不淘汰 | 小规模配置数据、字典表 |
| 仅 LRU(无 TTL) | 只依赖访问频率淘汰 | 计算密集型结果缓存,如编译缓存 |
实践要点:在 OpenAPI 网关中,建议对每个缓存条目同时设置 LRU 最大容量和 TTL。容量限制防止内存泄漏,TTL 保证数据最终一致性。对于极端热点数据,可考虑使用 Caffeine 的
expireAfterWrite + maximumSize 组合。