↓ 跳过正文

从 Cloudflare 故障看共享依赖:缓存、重试与降级边界

正能量5 分钟阅读

结合 Cloudflare 2025 年 6 月故障简要复盘,用业务系统案例解释共享存储如何扩大故障范围,以及缓存、重试预算、降级和恢复验证怎样配合。

地球、橙红色波形与告警标志组成的服务故障主题插画

登录、文件读取和后台操作同时报错时,很容易分别检查各个服务。另一个值得优先排查的方向是:它们是否都要读取同一份配置、身份信息或共享存储?服务数量很多,并不意味着故障域彼此独立。

Cloudflare 的一次故障提供了一个具体观察入口:关键存储路径失败后,上层多个服务随之受到影响。对于使用配置中心、Redis 和数据库的普通业务系统,类似依赖同样值得提前检查。

服务分布在多地,依赖仍可能集中
#

2025 年 6 月 12 日,Cloudflare Workers KV 依赖的底层存储不可用,进一步影响了依赖 KV 的多项服务,故障持续约两小时二十八分钟。事件没有造成数据丢失,部分其他基础服务未直接受影响。

分布在多个位置的服务,仍可能依赖一个关键的中心存储路径;上层服务复用这条路径,也会共享故障影响。部署拓扑和实际依赖拓扑,需要放在一起检查。

画出请求路径,才能看见共享故障域
#

设想一个由 Java 或 Go 实现的业务平台:商品服务读 Redis 缓存,鉴权服务读 Redis 中的会话,定时任务又用同一 Redis 保存任务锁。它们部署在不同容器、不同节点,代码也分属多个仓库,但某次 Redis 不可用可能同时触及三条业务路径。

这并不表示共享 Redis 一定错误。共享减少维护成本,也可能满足当前规模。需要被明确的是依赖关系和失败后果:哪些读取可以退回数据库,哪些判断缺少数据就必须停止,哪些任务允许稍后执行。

依赖图不要只画运行时调用。启动时加载配置、刷新令牌、定时续租和恢复时回填缓存,也可能在平时不显眼,却在故障期间集中触发。

缓存命中和缓存未命中是两种路径
#

如果缓存中已有商品资料,短时间内仍可能返回页面;新商品或过期条目需要回源,便可能失败。于是用户会看到“有些页面正常、有些不正常”,而整体进程与 CPU 指标都很平稳。

排查时可以分别观察命中率、回源次数、回源延迟和回源失败,而不只看总请求错误率。指标标签应控制数量,避免把每个用户或商品号都做成指标维度。

降级到数据库也有容量前提。若缓存承担了绝大多数读取,缓存故障后的全量回源可能把存储压垮。因此,“缓存不可用就查数据库”需要搭配并发上限、超时和流量优先级,不能只加一段异常捕获。

重试为什么可能把恢复拖慢
#

超时可以限制资源占用,重试有助于处理暂时故障,但也会放大过载;带副作用的调用即使超时,也可能已经执行,需要考虑幂等性。退避与随机扰动能够分散重试压力。

假设入口、业务服务和存储客户端三层都最多尝试三次,极端情况下,一次入口请求会产生 3 × 3 × 3 = 27 次底层尝试。实际次数取决于错误类型与调用结构,但重试预算逐层叠加的风险已经很清楚。

比“所有地方都增加重试”更明确的设计,是指定哪一层负责重试、哪些错误值得重试,以及整条调用链的总时限。上层已经放弃的请求,不应继续在下层排队消耗资源。

降级策略必须跟随数据语义
#

在这个业务平台中,不同功能可以有不同处理方式:

功能可考虑的降级行为需要守住的条件
商品介绍显示允许时效内的旧副本明确旧数据有效期
权限判断无法确认时停止敏感操作不能把读取失败解释为有权限
普通统计暂时不展示并提示稍后刷新不伪造为零或完整结果
重复任务控制暂停新执行并核对已有状态不因为锁存储异常就并发重跑

商品价格、库存和结算金额有各自规则。即使页面介绍允许使用旧副本,也不能自动把相同策略套到付款结果上。

fallback 方法能够被调用,只证明框架进入了后备分支。后备分支返回什么、会不会产生额外写入、调用者是否区分“无数据”和“暂不可用”,仍属于业务设计。

站内的缓存穿透、击穿与雪崩说明讨论了缓存失效的几种范围。沿着这个方向还可以再问一步:后备数据源是否与主路径共享连接池、网络出口或配置服务?如果这些条件相同,表面上的两条路径仍可能同时失效。

恢复阶段也需要流量控制
#

依赖恢复后,积压请求、定时任务和缓存回填可能同时启动。此时“连接重新建立”与“业务恢复稳定”并不等价。要确认队列长度是否下降、尾延迟是否稳定,以及错误是否随着流量恢复再次上升。

配额、负载削减和客户端节流,可以把流量控制在后端能承受的范围内。拒绝请求本身也会消耗资源;大量请求已经注定被拒绝时,应考虑在客户端提前抑制流量。

对小型系统,可以从最简单的措施开始:限制回填并发,为后台恢复任务设置速率,并先让核心读取恢复,再逐步增加非关键任务。这里不需要照搬大型平台的复杂调度,只需要让恢复流量有明确上限。

怎样让故障演练留下可检查结果
#

在隔离环境,可以把一次依赖故障演练分成四段:正常运行、依赖不可用、依赖恢复、流量回归。每段记录功能表现、下游请求量和资源占用。演练前确认测试数据、依赖地址和流量入口都属于隔离环境,并准备恢复到初始状态的方法。

验收应覆盖“没有额外影响”:例如依赖超时后,查询接口没有变成写入;鉴权未通过的操作没有执行;定时任务没有因为恢复重启而重复消费。这比单独检查某条错误日志更接近业务目标。

也可以把依赖异常区分为超时、明确拒绝和返回无效数据:三种表现可能触发不同分支。只模拟进程关闭,可能漏掉接口仍响应却迟迟不能返回有效结果的情况。

一份好的演练记录应能让下一位开发者判断:失败影响哪些功能、系统做出了什么选择、恢复是否需要人工介入,以及哪些假设还没验证。这些信息应进入运行手册和回归检查,避免下一次恢复时重新猜测。

参考来源
#