4. 缓存策略选型方案:LRU、LFU、TTL、W-TinyLFU 对比

4.1 策略边界与分层

缓存策略位于缓存架构的淘汰决策层,其边界是:接收缓存未命中后的空间释放请求,输出被淘汰的键和保留的键集。策略层不关心数据来源、序列化方式或网络传输,只关注“在容量达到上限时,哪些数据应该被移除”这一核心问题。

分层位置:
接入层(客户端/API) → 缓存读写层(get/set) → 淘汰策略层(LRU / LFU / TTL / W-TinyLFU) → 存储引擎层(内存表 / 持久化)

4.2 组件职责与核心机制

策略 淘汰依据 数据结构 时间复杂度 内存开销
LRU 最近一次访问时间 双向链表 + 哈希表 O(1) 中(维护链表指针)
LFU 访问频率(计数) 哈希表 + 频率链 / 最小堆 O(1) / O(log n) 高(维护频率计数)
TTL 过期时间(/相对) 优先队列 / 时间轮 / 惰性删除 O(log n) / O(1) 低
W-TinyLFU 频率 + 衰减 + 窗口 BloomFilter + LRU + 分段LRU O(1) 中(紧凑计数)
组件职责速记:
LRU 负责“最近用过,大概率再用”;LFU 负责“高频就是热点”;TTL 负责“时间到了就失效”;W-TinyLFU 综合“近期突发 + 长期热点”,通过窗口与衰减避免频率污染。

4.3 数据流与控制流分析

读写路径(数据流)

  • 读命中:返回数据 → 更新策略状态(LRU 移动到链表头;LFU 增加计数;W-TinyLFU 增加频率并调整分段)
  • 读未命中:从下游加载数据 → 写入缓存 → 触发容量检查 → 若超限则执行策略淘汰
  • 写操作:更新数据 → 重置 TTL / 重置频率或位置 → 容量检查 → 淘汰

淘汰决策流(控制流)

控制流的核心是“谁走谁留”的判定链路:

  1. 容量达到阈值(如 maxmemory / maxSize)触发淘汰;
  2. 策略模块读取当前所有候选键的元数据(时间戳 / 频率 / 过期时间);
  3. 按照策略排序规则选出“最应该淘汰”的键;
  4. 执行删除并更新内部数据结构;
  5. 如果仍有空间不足,重复 2–4 直到容量合规。
信任链路风险:LRU 在顺序扫描场景下会清空热点(“缓存污染”);LFU 在突发流量下无法快速响应新热点;TTL 依赖客户端设置合理过期时间,否则造成大量过期键堆积;W-TinyLFU 对窗口大小参数敏感,调参不当会退化为普通 LRU。

4.4 选型权衡决策

选型不能脱离业务访问特征与数据生命周期。以下决策模型将四种策略映射到典型场景:

缓存策略选型决策模型 访问特征分析 数据流 + 访问模式 LRU 最近最少使用 LFU 最不经常使用 TTL 过期时间淘汰 W-TinyLFU 窗口化TinyLFU 💡 选型要点:结合业务访问特征、数据生命周期与性能要求综合决策 突发新数据 → LRU | 稳定热点 → LFU | 有时效数据 → TTL | 混合场景 → W-TinyLFU

选型对比矩阵

策略 最适合场景 最不适合场景 典型中间件
LRU 突发流量、新闻热榜、用户会话 全表扫描、频繁全量遍历 Redis allkeys-lru、Memcached
LFU 长尾热点、商品详情、稳定排行榜 突发秒杀、瞬时新热点 Redis allkeys-lfu、Caffeine
TTL 验证码、临时令牌、缓存刷新窗口 无明确过期语义、热点数据反复过期 Redis expire、ETCD lease
W-TinyLFU 混合热点、CDN边缘、微服务本地缓存 超低内存设备(<1MB) Caffeine、Couchbase
决策口诀:
访问有突发 → LRU;访问有规律 → LFU;数据有时效 → TTL;既要又要 → W-TinyLFU。

4.5 风险点与避坑指南

  • LRU 缓存污染:一次全表扫描会冲掉所有热点。解决方案:使用 LRU-K 或分段 LRU(如 W-TinyLFU 的 Segmented LRU)。
  • LFU 频率老化:旧热点长期占据缓存,新数据无法晋升。解决方案:引入频率衰减因子(如每 N 分钟计数减半)。
  • TTL 过期堆积:大量键在同一时刻过期导致缓存雪崩。解决方案:TTL 抖动(在基础过期时间上增加随机偏移)。
  • W-TinyLFU 窗口误配:窗口太小则退化为 LFU,太大则退化为 LRU。解决方案:根据业务 QPS 分布动态调整窗口大小。
常见踩坑:线上直接切换策略(如从 LRU 切到 LFU)可能导致缓存大面积失效。必须灰度 + 预热后逐步切换,并在切换期间监控命中率和延迟。

4.6 落地实施步骤

  1. 访问特征采集:打点记录键的访问分布、频率衰减曲线、突发比例,持续采集 7 天以上。
  2. 策略仿真:用离线回放工具(如 cache-trace-sim)对比 LRU / LFU / W-TinyLFU 的命中率与驱逐次数。
  3. 参数配置:根据仿真结果设定容量、窗口大小、衰减系数、TTL 基准值。

以 Caffeine 为例,生产中启用 W-TinyLFU 的典型配置:

// W-TinyLFU 默认启用,无需手动指定策略
Cache<String, Data> cache = Caffeine.newBuilder()
    .maximumSize(100_000)                // 容量上限
    .expireAfterWrite(10, TimeUnit.MINUTES) // 写后过期
    .recordStats()                       // 开启命中率采集
    .build();
  1. 灰度上线:先放 5% 流量验证命中率和 P99 延迟,确认无误后全量。
  2. 持续调优:根据监控调整 maximumSize / TTL / 窗口参数,每季度复盘一次。

4.7 验收标准

维度 验收指标 合格线
命中率 整体缓存命中率 ≥ 95%(相对原策略不下降)
延迟 P99 读延迟 ≤ 2ms(含策略淘汰开销)
污染恢复 突发扫描后命中率恢复时间 ≤ 30 秒
内存稳定性 内存使用波动幅度 ≤ 10% 峰值内存
可观测性 策略决策次数、淘汰原因分布 100% 可记录与导出
验收 checklist:
✅ 策略与业务访问特征匹配
✅ 没有因策略切换导致缓存雪崩或大面积 miss
✅ 所有风险点已配置对应防护(衰减 / 抖动 / 分段)
✅ 灰度方案与回滚预案已就绪