缓存集群故障时系统如何降级和恢复?
简化版
缓存故障时不能把所有流量直接切到数据库。应先按数据风险启用本地旧值、静态兜底或明确失败,同时用熔断、回源限流和请求合并保护权威存储;缓存恢复后先验证拓扑和数据,再预热、限速回填、分批切流,避免冷启动造成第二次雪崩。
详细版
预案要区分单节点/分片故障、集群全断、网络慢、数据污染和跨机房故障。副本切换可处理局部节点退出,但异步复制可能丢失最近写;全断时按业务分级:推荐/详情可返回旧值或关闭,库存写/权限等高风险能力应回源强校验或失败关闭。
止血顺序是冻结高风险变更、隔离故障节点、限制重试、开启缓存熔断和数据库回源配额,并观察 DB QPS/连接/P99。旧值必须带版本和最大 stale 时间,不能永久兜底。若数据库也无容量,宁可限流/降级,不返回假成功。
恢复遵循“健康检查→拓扑稳定→热点预热→1% 灰度→逐步放量→处理积压/对账”。Key TTL 加抖动,在线 miss 合并;切流失败可退回旧集群/降级模式。演练要覆盖慢故障和空缓存恢复,而不只是 kill 节点。
完整版教学
一、先建立故障分类
缓存“不可用”可能是单主故障、部分 slot 超时、整个集群断连、跨区网络分区、数据被错误覆盖,或客户端路由/证书故障。不同类型的恢复动作相反:数据污染时继续读副本可能扩大错误,网络慢时无限重试会耗尽线程。
| 故障 | 主要影响 | 第一动作 |
|---|---|---|
| 单主故障 | 部分 slot 短暂不可用 | 确认副本提升、限制重试 |
| 单分片慢 | P99 与连接池堆积 | 隔离慢分片、短超时 |
| 全集群断连 | 命中归零 | 熔断缓存、受控兜底 |
| 数据污染 | 返回错误值 | 冻结写、按版本隔离污染 |
| 跨区故障 | 延迟/路由变化 | 切就近灾备、控制一致性 |
| 客户端配置错误 | 大范围连接失败 | 回滚配置/SDK,勿盲目扩容 |
记忆钩子:容灾的第一目标不是让缓存立刻恢复,而是阻止缓存故障继续拖垮数据库和核心业务。
二、为什么直接回源数据库会雪崩
正常 8 万 QPS、命中率 98.75% 时,数据库约接 1000 QPS。缓存全断后直接回源会变成 8 万 QPS,是原来的 80 倍;数据库变慢又触发超时重试,压力更高。
回源必须由数据库安全余量决定。假设数据库安全上限 6000 QPS,现有必须流量 1500,保留 1500 故障余量,则缓存回源最多 3000 QPS。其余请求按优先级使用旧值、静态内容或快速失败。
fallback_budget = db_safe_capacity - mandatory_traffic - headroom
所有应用实例共享预算,不能每实例各设 3000 QPS
三、降级矩阵如何设计
先按错误结果的代价决定 fail-open 或 fail-closed。商品描述可读本地快照,推荐模块可隐藏;权限撤销和风控不确定时通常失败关闭;库存展示可以旧,但下单必须权威校验。
旧值缓存包含 generatedAt、dataVersion 和 staleUntil。故障时只有未超过上限才返回,并在响应中标记降级。若本地没有可信旧值,不能用默认“有库存/有权限”伪造业务事实。
静态兜底也要控制版本与安全。灾备包可能数月未更新,演练时应检查其内容、链接和隐私,而不只是页面能打开。
四、局部故障切换的复制边界
主从异步复制下,主返回成功的写可能尚未到从。副本提升后,最近缓存写/删除可能丢失,出现旧 Key 复活。缓存可从数据库重建,不代表错误旧值无害;切换后可对关键 namespace 定向失效或校验版本。
客户端需及时刷新拓扑,限制 MOVED/连接重试,避免仍打旧主。旧主恢复后必须以从角色追赶,不能同时接受写。使用 WAIT/最小副本策略可缩小窗口,但会增加延迟并降低分区时写可用性。
脑裂风险还要求新旧主的写权限由集群协议和网络隔离控制,不能只依赖客户端“应该访问新主”。
五、全量恢复为什么要慢启动
新集群/清空后的缓存命中率接近零,全量切流等同数据库直连。先从历史 Top Key、活动清单或可信快照预热;在线 miss 使用 singleflight 和全局回源限流;TTL 加抖动。
切流可按租户或用户哈希 1%→5%→20%→50%→100%,每级观察命中、Redis P99、数据库 QPS、错误和复制 lag。不要只看集群节点绿色;数据是否热起来决定能否承载。
基础设施恢复 -> 数据/版本校验 -> Top Key 预热
-> 少量流量 -> 观察 -> 逐级扩大
-> 退出旧值降级 -> 对账与复盘
六、数据污染的恢复不同于节点故障
错误程序可能写入坏值或错误 TTL,并迅速复制到所有副本;此时切从节点没有用。需要确定污染时间、Key 前缀、版本和权威数据,停止污染写入,按范围重建。若无版本和审计,只能大范围删缓存,风险更高。
恢复不能从已污染缓存复制,应从数据库、事件日志或已验证快照重建。大范围清理采用版本化 namespace 或限速 UNLINK,并同时限制回源。新旧版本并存便于灰度和回滚。
缓存集群备份的价值也有限:过旧快照可加速预热,但恢复后仍需增量失效和版本校验,不能把缓存备份当唯一事实源。
七、演练与可观测性
演练矩阵包括 kill 主节点、单向丢包、延迟 500ms、证书/密码错误、全量空缓存、错误批量写和恢复切流。预先写明不变量:数据库不超过安全 QPS、权限不失败开放、核心写不假成功、恢复期间无持续淘汰。
指标包括故障分片数、熔断状态、旧值返回率/年龄、回源预算使用、DB 余量、预热进度、灰度比例、复制 lag、拓扑版本和恢复时间。RTO 要定义恢复到何种能力,不是进程重启时刻。
mode: CACHE_DEGRADED
db_fallback_qps: 2840
db_fallback_budget: 3000
stale_response_rate: 12%
stale_age_p99_seconds: 46
warmup_progress: 72%
traffic_on_recovered_cluster: 20%
八、常见误区与追问
- 误区:缓存故障后回源数据库最正确。 正确性不代表容量安全,全量回源会把故障扩散到事实源。
- 误区:缓存数据可丢,所以无需考虑主从丢写。 删除复活和旧权限仍可能造成业务错误。
- 误区:节点恢复健康即可全量切回。 空缓存/冷缓存会制造回源洪峰,必须预热和灰度。
- 误区:所有数据都适合本地旧值兜底。 权限、风控和资金相关数据可能必须失败关闭。
- 追问:数据库也不可用怎么办? 只返回可证明安全的 stale/静态结果,核心写明确失败或受理为待处理,不能假成功。
- 追问:如何防恢复时缓存雪崩? Top Key 预热、singleflight、全局回源限流、TTL 抖动和分批切流。
- 追问:RTO/RPO 如何定义? RTO 是恢复到指定业务能力的时间;RPO 取决于缓存是否权威及异步复制窗口,可重建缓存也要定义陈旧影响。
九、加强记忆
缓存容灾按“先保数据库、再分业务降级、最后慢恢复”执行。局部故障关注副本切换与旧值复活,全局故障用熔断、共享回源预算和有限 stale 止血,数据污染则从权威源重建。基础设施恢复后仍要预热、灰度和对账,避免把一次故障恢复成第二次雪崩。