研究报告 · 约 27,666 字 · 预计推送 3 部分

缓存工程实践:旁路缓存、失效策略与雪崩/穿透/击穿防御(综合报告) 未开始

目录

题记与说明

综合说明:本报告由课题两份章节综合而成——纵轴章(发展脉络 1970–2026)与横轴章(2026-11-05 时间截面横向对比)。两章主要事实均在撰写当日经 WebSearch / 网页读取检索验证并随文附来源 URL(个别背景性陈述未附链接,folklore 类内容随文明确标注);本稿为按独立审读意见修订后的终稿,统一了两章间的版本表述(Redis/Valkey 版本号、淘汰策略建议等差异点在正文以括注说明),并合并了两章重复的"个人服务落地清单"(见第三节)。第三方 benchmark 数字未在本机复测,仅作定性参考。撰写日期:2026-11-05。

TL;DR

旁路缓存(cache-aside)自 2003 年 memcached 定型至今从未被替代,演化的是围绕它的失效防御体系。击穿防御链清晰:互斥锁(nginx 2011)→ 租约(Facebook 2013)→ 单飞(2013/2016)→ 概率提前过期(XFetch 2015 → Cloudflare 2024 落地)→ 库内建默认(HybridCache)。雪崩/穿透/击穿三分法是中文社区 2017 年定型的本土词典,英文统称 cache stampede。引擎层正被许可证大战重排(Redis 8 vs Valkey),但缓存模式横跨所有引擎原样成立——模式比引擎稳定一个数量级。个人服务用三件套(TTL 抖动、进程内单飞、空值缓存+参数校验)即可覆盖三类事故的主要攻击面,分布式锁与布隆过滤器默认不上。

三个核心词,先记住再说(详细展开见第二节"先厘清三个词"):

- 雪崩:大量 key 同时过期(或缓存层整体宕机),请求洪峰直接砸向数据库;
- 击穿:单个热 key 过期瞬间,海量并发同时回源(= 只打一个洞的雪崩);
- 穿透:查询根本不存在的数据,缓存永远不命中,每次都穿透到库(常为恶意扫描)。

一、纵轴:发展脉络(1970–2026)

一条主线

缓存工程二十多年的演化可以概括为一句话:它从"给数据库打的临时补丁"(2003 年的 memcached),长成了拥有自己的故障分类学(雪崩/穿透/击穿)、防御工具箱(租约/单飞/概率提前过期/逻辑过期)和治理体系(TTL 治理、热点治理、许可证治理)的一门工程学科。而驱动每一次跃迁的从来不是缓存本身,而是"回源代价"的变化——回源到数据库、回源到第三方 API,如今还包括回源到按 token 计费的 LLM。

阶段一:问题域的奠定(1970–2002)

驱动因素:Web 流量爆炸使"重复计算/重复回源"第一次成为产业级问题,缓存失效之"难"在这一时期成为共识。

阶段二:旁路缓存定型——memcached 与第一代分布式缓存(2003–2008)

主要参与者:Brad Fitzpatrick、Anatoly Vorobey、dormando、Dustin Sallings;Digg、Slashdot、Wikipedia 等早期 LAMP 大站。驱动因素:Web 2.0 流量激增 + 单机数据库瓶颈——"内存哈希表 + 文本协议"的极简设计把缓存从进程内技巧变成了可水平扩展的网络基础设施。

阶段三:大规模生产验证与机制化(2009–2013)

驱动因素:Facebook/Twitter/Netflix 级流量把缓存从组件升格为独立架构层;一致性(stale set)、击穿(lease 扣发)、跨区失效传播第一次被论文化。

阶段四:方法论体系化与中文社区词典定型(2014–2018)

驱动因素:国内移动互联网大促(双 11/618)的极端脉冲流量叠加面试文化,把问题域"词典化";学术界(XFetch、TinyLFU)与工业界(lease、singleflight)在击穿问题上正式会师。

阶段五:精细化治理——热点、多线程与体验优化(2019–2023)

驱动因素:热点经济(明星、秒杀、爬虫)、多云架构、前端体验指标(Core Web Vitals),以及 LLM 的 token 成本——"回源代价"被推到新维度。

阶段六:分叉、回归与当下(2024–2026)

驱动因素:云厂商与独立软件公司利益失衡 → 许可证武器化 → 社区分叉;主战场从"防数据库崩溃"扩展到"防 LLM 账单爆炸"。

纵轴各阶段一览表

阶段关键版本/事件主要参与者驱动因素
1970–2002布隆过滤器、thundering herd、RFC 2616OS/学术/HTTP 社区Web 流量爆炸
2003–2008memcached(2003)、dogpile effectBrad Fitzpatrick 等Web 2.0、单机 DB 瓶颈
2009–2013Redis(2009)、RFC 5861、nginx cache lock、Spring 3.1、NSDI'13 lease、singleflightantirez、Facebook、mnot、Fitzpatrick超大流量公司的架构层化
2014–2018Caffeine/TinyLFU、XFetch、Spring sync、美团《缓存那些事》、Redis Cluster/LFUNetflix 系、Ben Manes、美团/阿里大促脉冲流量 + 面试文化词典化
2019–2023JD-hotkey、Redis 6 多线程、SWR、GPTCache京东、antirez、Zilliz热点经济、前端体验、LLM 成本
2024–2026许可证变更、Valkey 分叉、Redis 8 AGPL、无锁概率缓存Linux Foundation、Redis Ltd.、Cloudflare供应链政治、AI 时代回源代价

二、横轴:横向对比(2026-11-05 时间截面)

对比对象的选取与维度

"缓存工程实践"是模式与工程层的课题(怎么用缓存、怎么防失效事故),但工程实践从不孤立于引擎存在——你选的策略必须落在某个缓存实现上。因此在当下时间截面上,对比对象拆成三个平面:

对比维度:能力、性能与资源成本、经济成本(许可证/托管)、生态、成熟度与维护状态、适用场景。

先厘清三个词:雪崩 / 穿透 / 击穿

这三个词经常被混用,但防御手段完全不同(核心定义已前置到 TL;DR 之后,此处展开并补充英文对应与出处):

英文社区对前两者一般统称 cache stampede / thundering herd(Wikipedia: Cache stampede),不细分这三层;三分法是中文社区对同一问题域的本土切分(见纵轴阶段四,2017 年《缓存那些事》定型)。

平面 A:分布式缓存服务器横向对比

维度Redis 8Valkey 9DragonflyKeyDBMemcached 1.6Garnet
治理/出身Redis Ltd.,参考实现Linux Foundation 项目(2024-03 自 Redis 分叉,AWS/Google 等支持)DragonflyDB 公司2022-05 被 Snap 收购,此后开发节奏放缓由长期维护者 dormando 个人维护Microsoft Research
许可证三选一:AGPLv3 / RSALv2 / SSPLv1(2025-05 起)BSD-3(完全开源)源码可用(第三方对比归为 BSL 1.1,未核读 LICENSE 原文)BSDBSDMIT
线程模型命令执行单线程(I/O 可多线程)同 Redis 血统,单线程为主每核一线程、shared-nothing + fiber多线程(EF RR 轮询)多线程.NET 8,多线程,Tsavorite 日志式存储
数据结构/能力最全:String/Hash/List/Set/ZSet/Stream + 8 内置结构(JSON、TimeSeries、Bloom/Cuckoo/CountMin/TopK/TDigest、Vector Set beta)+ 查询引擎与 Redis 高度兼容;9.0 新增 hash 字段级过期、原子 slot 迁移、集群多 DB兼容大部分 Redis API(RESP),模块生态最弱Redis 兼容,功能面略滞后仅扁平 KV + slab 管理,无持久化保障(extstore 提供磁盘分层)支持 String/ZSet/Bitmap/HyperLogLog 等常用面,无完整集群
持久化/高可用RDB+AOF、主从、Cluster同 Redis 血统快照;集群能力在演进支持无内建 HA检查点;单节点为主
性能(第三方基准,定性)基线;Redis 8 官方称 30+ 项改进、最高快 87%与 Redis 接近,8.0/8.1 内存效率与延迟显著改善多数第三方测试中最快、内存效率最好(官方称 30–60% 更省内存)近期社区基准中吞吐偏低中小规模够用,规模上限低多核服务器上单节点吞吐显著优于 Redis(VLDB 论文主张)
生态最强(客户端库、框架适配、托管服务最多)快速上升,主流云托管(ElastiCache/Memorystore)已支持增长中,兼容 Redis 客户端缓慢老牌稳定.NET 生态友好,其他语言经 RESP 可用
适用场景默认选项;需要查询引擎/概率结构/向量时想要 OSI 开源 + 云厂商托管对齐者单机大内存、多核、重吞吐热点存量用户维护极简 KV、早期生态绑定.NET 栈、多核大内存单机场景

逐项要点与来源:

平面 B:进程内本地缓存横向对比

维度Caffeine(JVM)Guava CacheRistretto / Otter(Go).NET HybridCache自制 map+TTL
淘汰策略W-TinyLFU(准入窗口 + Count-Min 频率草图),命中率接近最优分段 LRURistretto:TinyLFU 准入 + 成本淘汰;新锐 Otter 主张更优依赖底层 L1 实现自定(通常无淘汰或简单 LRU)
并发设计无锁环形缓冲 + 条带化锁竞争明显(多年 backlog 的瓶颈修复)高吞吐、带宽友好内建合并锁看实现
性能(定性)官方 JMH 基准大幅领先 Guava,个别淘汰场景达 25×基线高吞吐未主打性能,主打正确性—
框架地位Spring Boot 2.x 起默认本地缓存;Spark 也从 Guava 迁移(SPARK-34309)老牌、存量巨大Dgraph/Badger 内核出身;社区提醒其维护趋缓.NET 9 GA(2025-03),微软官方零依赖
独有能力频率感知淘汰、刷新前异步 reload简单 API成本模型(按字节预算)L1+L2 双层、内建防击穿合并、tag 失效—
适用场景JVM 服务本地 L1 的默认解遗留代码Go 高并发热点.NET 服务"一键两层缓存"个人小服务/流量极低时

逐项要点与来源:

平面 C-1:缓存读写模式横向对比

模式读路径写路径一致性实现方主要风险权威来源
Cache-Aside(旁路缓存,课题核心)应用先查缓存,miss 则查库并回填应用写库,删除缓存最终一致(脏读窗口=TTL)应用自己写旧值回填、并发写竞态Azure Cache-Aside 模式、AWS ElastiCache 缓存策略
Read-Through缓存层自己负责 miss 后加载模式本身不约定;常见做法同 cache-aside(更新库后删缓存)类似 cache-aside缓存库/中间件需要库支持 loaderAWS ElastiCache
Write-Through—同步写缓存+库强(读己之写)缓存库写延迟高;AWS 提醒两点:节点故障/重启后缓存被清空、数据需另行重建(常退回 cache-aside 补);写入却从不被读的数据白占缓存、挤出热点 keyAWS 缓存最佳实践
Write-Behind / Write-Back—先写缓存,异步批量写库弱(缓存挂→丢数据)缓存库数据丢失窗口Hazelcast 模式指南、Redisson 术语表
Refresh-Ahead到期前主动刷新热 key—好(热 key 几乎无 miss)缓存库/定时任务刷新浪费(冷 key 也刷)Redis 官方博客:缓存策略

要点:Cache-Aside 之所以是默认范式,是因为它把复杂度最小化——应用可控、库无关、写路径简单("更新 DB 后删缓存"而不是"更新缓存")。代价是一致性上限低(TTL 内脏读)与 miss 需要应用自己兜底——这正是雪崩/穿透/击穿三类事故的根源。至于表中列出的"旧值回填、并发写竞态"两个风险,最低限度的对策只有两条:回填一律带 TTL(任何旧值都有兜底过期上限)、只删缓存而不更新缓存(把竞态窗口压缩到"一次回源耗时"量级);个人服务做到这两条即可接受,出现"多实例高频写同一 key"或"读方对秒级旧值敏感"的信号时才需要升级(版本号比对、延迟双删等,见第三节清单第 4 条)。

平面 C-2:雪崩/穿透/击穿防御方案横向对比

方案针对问题原理实现成本失效场景/代价来源
TTL 随机抖动雪崩过期时间加 ±20% 随机量,错峰极低无实质失效;脏读窗口被拉宽AWS 缓存最佳实践
空值缓存穿透不存在的 key 也缓存(短 TTL,30–60s)低内存小耗;攻击 key 完全随机时防线弱;脏窗口小林coding、cnblogs 专题
布隆过滤器穿透概率成员判断,不存在则直接拦截中(Redis 8 已原生内建)误报(可能放过)、不能删(Cuckoo 可删)、需周期重建Redis 布隆过滤器文档、阿里云开发者社区
互斥锁(SETNX/分布式锁)击穿同 key 只放一个请求回源,其余等待中(要处理超时/死锁/等待队列)等待拖长 P99;锁服务故障反成新风险小林coding
singleflight 请求合并击穿进程内同 key 并发合并为一次调用(Go x/sync/singleflight 的 Do/DoChan)低仅进程内有效;多实例时每实例各合并一次pkg.go.dev/singleflight
逻辑过期(异步重建)击穿+雪崩物理不设 TTL,值内存放逻辑过期字段,过期后后台异步刷新,读请求立即返回旧值中高短暂脏读;实现复杂OneUptime: Redis Cache Stampede
概率提前过期(XFetch)击穿+雪崩按剩余寿命概率性提前重建:软过期时刻 = time + β·ln(1/rand)·Δ(rand∈(0,1) 时提前量恒为正;等价判定式:距上次重建超过 β·Δ·ln(1/rand) 即刷新——与纵轴阶段四所引判定式同式),被证明最优低中(β 需调参)需要能预估回源耗时 Δ(= E[recompute])Vattani et al. 2015 论文、Wikipedia: Cache stampede 伪代码、Go 实践
接口参数校验/限流熔断穿透+雪崩非法 ID 直接拒绝;缓存层故障时限流降级读库低拦不住"合法但不存在"的 key小林coding
多级缓存(L1+L2)雪崩+击穿L1 吸收热点与 L2 故障,L2 提供共享中(一致性管理变复杂)L1 加剧脏读与失效广播复杂度HybridCache 文档
缓存层高可用雪崩主从/集群,避免单点宕机即雪崩架构级成本上升Dragonfly: Valkey vs Redis 指南

逐项点评:

  1. 没有银弹,只有组合拳。中文社区的主流实践结论一致:穿透用"参数校验 + 空值缓存 +(必要时)布隆过滤器"三层递进;击穿用"互斥/合并 + 逻辑过期"二选一或并用;雪崩用"TTL 抖动 + 多级缓存 + 限流降级"。来源:阿里云开发者社区、掘金实践、VergeCloud。
  2. 布隆过滤器不是免费午餐:误报、无法删除(Cuckoo Filter 弥补)、数据更新后需重建;社区建议"资源有限或脏数据少时优先空值缓存,海量不存在 key 请求时才上布隆"(cnblogs)。
  3. singleflight 是击穿防御的性价比之王(单实例场景):官方语义就是"对同一 key 保证只有一个执行在途,重复调用者等待并共享结果",是 Go 生态处理击穿的事实标准;.NET HybridCache 把同一语义做成默认行为(pkg.go.dev、GA 公告)。
  4. XFetch 提供理论最优但工程采用率低:2015 年论文证明了概率提前过期在"浪费的提前重建"与"击穿概率"之间的最优权衡,零协调、无需锁,但需要预知回源耗时且参数难解释;实战中 singleflight + TTL 抖动仍是绝对主流,直到 2024 年 Cloudflare 才将其落地生产(XFetch 论文、Kit 工程实践、Cloudflare: Sometimes I cache)。

选型总览:三层一张表

层选项一句话定位默认推荐(2026-11 截面)
引擎Redis 8参考实现 + 最全能力✅ 一般推荐(注意 AGPLv3 合规)
引擎Valkey 9开源 + 云厂商对齐✅ 想规避 Redis 许可纠结时
引擎Dragonfly多核重吞吐重写仅在大单机热点时
引擎KeyDB / Memcached存量维护新项目不再首选
引擎Garnet.NET 栈试验田.NET 且多核单机时
库CaffeineJVM L1 默认解✅ JVM 项目
库Otter/RistrettoGo L1✅ Go 项目(先看维护活跃度)
库HybridCache.NET 双层+防击穿内建✅ .NET 项目
模式Cache-Aside + TTL 抖动写路径简单的最终一致✅ 一切读多写少场景
模式singleflight / 逻辑过期击穿防御✅ 默认 singleflight;上游容忍旧值时叠加逻辑过期保体验
模式空值缓存 + 参数校验穿透防御✅ 默认;布隆过滤器按需
模式XFetch理论最优提前刷新量化控团队可选

三、交叉洞察:两轴结合说明了什么

把纵轴的"从哪来"与横轴的"现在在哪"交叉,能得到六条单轴得不到的判断:

洞察一:回源代价决定缓存形态,且每次变贵都重演同一套防御

纵轴的主线是"回源代价"的三次跃迁:回源到数据库(memcached 时代)→ 回源到第三方 API(Cloudflare Workers 时代)→ 回源到按 token 计费的 LLM(GPTCache 时代)。横轴印证了其结构同构性:布隆过滤器防的是"不该到库的请求",语义缓存防的是"不该到模型的 token"——防御的对象换了,雪崩/穿透/击穿的分类框架原封不动。判断任何新缓存场景(如 Agent 工具调用结果缓存)时,可以直接套用这套分类学与工具箱,不必重新发明。

洞察二:模式比引擎稳定一个数量级——这是两轴交叉给出的最重要结论

横轴显示:2024–2025 两年间,许可证大战把引擎市场彻底重排(Redis 弃 BSD → Valkey 分叉 → Redis 8 以 AGPLv3 回摆),六款引擎各有兴衰;但 cache-aside、TTL 抖动、单飞合并、空值缓存这些模式横跨所有引擎原样成立。纵轴给出同样的证据:memcached → Redis → Valkey 引擎换了三代,cache-aside 自 2003 年定型至今从未被替代。推论:工程实践的精力应优先投在模式与纪律上;引擎选型是可逆决策,模式选型不是。(这一结论由横轴的引擎兴衰对比与纵轴的 cache-aside 跨代存续证据共同支撑。)

洞察三:击穿防御的演化方向是"去中心化 + 下沉到库",手写分布式锁是过渡形态

纵轴的演化链:缓存锁(nginx 1.1.12,2011)→ 租约(Facebook NSDI'13)→ 单飞(singleflight 2013、Spring sync 2016)→ 理论最优概率提前过期(XFetch 2015,Cloudflare 2024 落地)——从"互斥"走向"无锁概率"。横轴补上当下坐标:HybridCache 把合并语义做成默认开启,Valkey 9 的 hash 字段级过期把失效粒度做成引擎原生。两轴连起来看,趋势是防御从"应用自己写"逐级下沉为"库的默认能力"再下沉为"引擎原生能力"。推论:新项目里手写分布式锁防击穿的教程代码会越来越少;选库时把"是否内建防击穿合并"当作默认考量项。(RedLock 之争提醒了下沉的边界:Kleppmann 2016 年的批评仍然有效,分布式锁不是免费的正确性。)

洞察四:理论最优 ≠ 工程主流,标准化慢于实践——采用率由工程成本决定

XFetch 是最好的标本:2015 年就有理论最优解、零协调、无需锁,但因为需要预估回源耗时、参数难解释,实战中 singleflight + TTL 抖动一直占绝对主流,直到 2024 年 Cloudflare 才找到大规模落地的形态。同理,RFC 5861(2010)定义 stale-while-revalidate,到 CDN 完全异步实现(2026-02-26)隔了整整 16 年。两轴交叉说明:一个防御手段能否普及,取决于可解释性、可调参与实现成本,而不是理论优美度;同时要接受"标准与实践之间存在十年量级的时差"。

洞察五:中小规模下引擎性能差异是伪问题,一致性失效才是真问题

横轴的引擎对比显示 Dragonfly/Garnet 吞吐领先是真实的,但触发条件是多核大内存高并发;纵轴的 Redis 6.0 多线程 I/O 演化同样说明,单线程瓶颈只在超大规模出现。绝大多数服务(更不必说个人服务)的流量远未触及 Redis 单线程模型的吞吐上限。而 cache-aside 的脏读窗口、miss 竞态、失效传播,是每一个用缓存的项目都必须面对的。选引擎的真正变量是许可证、托管可用性与运维熟悉度,而非吞吐数字;选模式的真正变量是数据能容忍多旧。

洞察六:L1+L2 成为新默认架构,而防御的另一半在"收敛输入";极限处承认失效之难

纵轴上 Caffeine(2015-12)与横轴上 HybridCache(.NET 9 GA)合起来,说明进程内缓存已从"dirty hack"升级为一等公民:L1 天然吸收热点与 L2 故障(雪崩与宕机兜底),库内建合并天然吸收击穿——"L1+L2"成为新默认架构。另一半防御在"收敛输入":参数校验、空值缓存、布隆过滤器解决的都是"不该到库的请求到了库",把缓存问题前移成 API 治理问题。最后承认极限:缓存失效永远难——从 Phil Karlton 的名言到 Facebook 的 remote markers,再到 canal 的 binlog 订阅,人类不断用更重的基础设施回避"本地删除到底够不够"这个问题;个人服务的答案便宜得多:接受最终一致,让 TTL 做最后一道保险。

对用户的判断与建议(附两章合并后的个人服务落地清单)

三条总判断:

  1. 先问要不要,再问怎么防:静态/半静态内容直接上 CDN/反向代理缓存,不进应用层;读多写少才值得 cache-aside;强一致数据(支付、余额)直接绕过缓存查库——这比任何失效策略都便宜。
  2. 三件套覆盖三类事故的主要攻击面:TTL 随机抖动(防雪崩)、进程内单飞(防击穿)、参数校验+空值缓存(防穿透)——零依赖、一天内可落地。
  3. 默认不上的两样东西:分布式锁(个人/中小服务并发量到不了,复杂度与故障面不成比例,且 Kleppmann 的 RedLock 批评适用)与布隆过滤器(key 空间不大时,重建与误判成本高于收益)。

个人服务落地清单(由纵轴与横轴两章各自的落地清单合并而成,消除了两处表述差异:缓存引擎统一为 Redis 8 / Valkey 9 当下版本;淘汰策略统一为"缓存场景优先 allkeys-lfu,简单默认可用 allkeys-lru"):

  1. 【选型·第 0 步】内容静态或半静态(博客、文档站)?→ 不需要应用层缓存,直接 CDN/反向代理缓存(如 Cloudflare 免费档)。
  2. 【选型】单进程先不引 Redis:本地字典 / Caffeine / Python cachetools 已足够;确需跨进程共享,再上单机 Redis 8 或 Valkey 9(Docker 跑在 VPS 上;个人自用推荐 Valkey——BSD 许可,无商用授权焦虑),maxmemory 设为实例内存的 1/3,淘汰策略缓存场景优先 allkeys-lfu(Redis 4.0+ 内建,抗偶发扫描污染),简单默认 allkeys-lru 亦可。
  3. 【选型·托管】完全不想运维(Vercel/Workers 等平台部署)?→ Upstash Redis 免费档:每月 50 万条命令 + 250MB,超出后按 $0.20/10 万条计费(Upstash 定价、定价公告);按命令计费对抖动负载不可预测,给消费设上限。
  4. 【旁路缓存标准化】读 = 查缓存 → miss → 查库 → 回填 TTL;写 = 更新库 → 删除缓存键(不要更新缓存、不要先删缓存再更新库)。TTL 取"业务可容忍陈旧度"的 1/2–1/3。平面 C-1 风险列提到的"旧值回填、并发写竞态",个人服务可接受的理由:写并发低,竞态窗口只有一次回源耗时(毫秒级),且最坏结果被 TTL 上限框住——TTL 本身就是兜底;在出现"多实例高频写同一 key"或"读方对秒级旧值敏感"的信号之前,守住这一条即可,无需延迟双删等升级手段。
  5. 【防雪崩】TTL 一律加随机抖动:ttl = base ± rand(0, base*0.2);批量预热不要让所有 key 同秒过期。
  6. 【防击穿】进程内单飞:Go 用 golang.org/x/sync/singleflight;Java 用 Caffeine LoadingCache 或 @Cacheable(sync=true);.NET 直接用 HybridCache(内建、默认开启);Python 用 per-key asyncio.Lock。互斥范围到"本进程"即可,不要为个人服务引入 Redis 分布式锁。
  7. 【防穿透】参数校验前置(id 范围/格式,非法直接 400)——这是免费的第一道闸;miss 时缓存空值(短 TTL 30–60s)。布隆过滤器默认不上,仅当 (a) 遭受真实恶意扫描且 (b) key 集合稳定可重建时,才用 Redis 8 原生 BF.ADD/BF.EXISTS。
  8. 【保体验】宁可返回旧值:逻辑过期/后台刷新(SWR 思想)——命中时判断"已软过期"→ 返回旧值并异步刷新;统一口径(与选型总览一致):默认 singleflight;上游容忍旧值时叠加逻辑过期保体验。
  9. 【内存有界】Redis 设 maxmemory + 淘汰策略;本地缓存设容量上限(如 Caffeine maximumSize)。缓存把宿主机内存吃爆,等于自造一场雪崩。
  10. 【脏读兜底 = TTL】接受"缓存内是旧数据"这一事实,TTL 是一切失效逻辑失败时的最终一致性保障;据此给每个 key 设 TTL 上限。绝大多数读多写少的数据对秒级旧值无感;强一致数据绕过缓存。
  11. 【降级路径】缓存挂了不等于服务挂了:读路径 try-catch 后回源 + 限流(一个简单的信号量/计数器即可)+ 进程内兜底 TTL 缓存;写一个"缓存不可用"开关并实际演练一次,避免缓存故障放大为数据库故障。
  12. 【可观测】必看的四个数:命中率(Redis INFO 的 keyspace_hits/keyspace_misses)、evictions(evicted_keys)、回源 QPS/P99 延迟、缓存层错误计数——打到日志即可,不必上 APM。没有命中率统计的缓存等于没有缓存。
  13. 【热点预案】个人服务单实例基本无热 key 问题;若多实例,热 key 用"本地短 TTL(1–5s)一级缓存 + Redis 二级"双层即可,无需 JD-hotkey 级别的框架。
  14. 【演练一次雪崩】上线前用 wrk/vegeta 以"全部缓存为空"的冷状态压测一遍,确认数据库在 miss 风暴下不挂——这是个人服务唯一一次值得做的压测。

四、参考来源

以下链接均来自两份章节的撰写当日检索验证(少数为本终稿修订时补验);folklore 类(Phil Karlton 名言、延迟双删等)已明确标注,不冒充文献。

起源与标准

论文与工业实践

引擎层现状(2024–2026)

模式与防御

个人服务成本

← 资料库今日播报 →