← 返回题目列表

什么是分布式系统的退化模式?

中等 第 26 / 27 题 更新于 2026/09/30
退化模式降级故障恢复状态机
学习 AI 实战项目

简化版

退化模式是系统在依赖故障、资源不足或数据不完整时,主动切换到能力更弱但边界明确的运行状态,例如只读、返回旧缓存、暂停非核心写入。它不同于临时异常兜底:必须预先定义进入条件、允许行为、数据语义、退出条件和恢复后的追赶流程。

详细版

退化模式的目标是避免局部故障演变为全站不可用,同时守住核心业务不变量。常见形态包括只读模式、缓存只读、关闭推荐/搜索增强、异步受理、静态兜底和按优先级丢弃。选择哪种模式取决于故障期间允许旧到什么程度、哪些写绝不能接受、用户是否需要知道结果仍在处理中。

它应被建模为显式状态机,而不是散落的 if (error) return cache。系统要定义进入阈值和持续时间,防止指标抖动导致频繁切换;进入后冻结或记录无法完成的动作;恢复时先验证依赖健康,再限速回放积压、对账和逐步放量。

退化不等于返回假成功。支付依赖故障时可以把订单标为待确认,但不能直接显示支付成功;权限事实不确定时通常应失败关闭。所有退化响应都应可观测、带来源/新鲜度,并有演练证明恢复不会产生重复或覆盖新数据。

完整版教学

一、退化模式与普通降级有什么区别

“降级”常被泛指关闭一个功能,退化模式更强调系统进入一种持续、可解释的运行状态。正常模式与退化模式拥有不同的能力集合、数据语义和恢复流程;它可能持续几分钟甚至数小时,而不是一次请求的异常分支。

例如主库不可写后,商品站点进入只读模式:允许读取最近缓存,禁止价格和库存修改,并在页面展示更新时间。这个模式要在主库恢复后完成缓存验证和写入口放量,不能开关一关一开就算结束。

易错点:退化模式不是“无论如何返回成功”,而是在能力变弱时仍诚实表达结果,并守住不能破坏的业务底线。

二、先按业务不变量决定能退化到哪里

同一种故障对不同业务的安全边界不同。推荐服务不可用可以返回热门榜;库存服务不可用时继续承诺“下单成功”可能超卖;风控服务不确定时,高风险支付通常应拒绝而非放行。退化方向必须由业务风险决定。

场景可接受退化不可接受行为
商品详情返回 60 秒内缓存把未知库存显示为有货
推荐热门榜或关闭模块阻塞核心页面数秒
订单查询返回带时间戳的旧快照把旧状态标成实时状态
支付确认显示处理中并异步查询未确认就显示成功
权限校验高风险操作失败关闭因缓存缺失默认放行

设计评审应明确数据允许旧多久、能否补偿以及错误决定的损失上限。

三、把退化建模为状态机

布尔开关难以描述准备、退化、恢复和失败回退。至少可设计 NORMAL -> DEGRADED -> RECOVERING -> NORMAL,并保留人工强制状态。每次迁移都有条件、操作者和审计记录。

NORMAL --连续3个窗口错误率>5%--> DEGRADED
DEGRADED --依赖连续5分钟健康--> RECOVERING
RECOVERING --回放完成且指标正常--> NORMAL
RECOVERING --错误再次超阈值------> DEGRADED

进入和退出阈值应不同,形成滞回,避免错误率在 5% 附近抖动时反复切换。自动触发还要有最长持续时间和人工接管机制。

四、退化期间的数据怎么处理

只读模式最简单,因为不产生新写;若需要“异步受理”,则必须可靠保存用户意图。比如依赖故障时接收退款申请,可以先写本地申请表并返回 PENDING,待恢复后处理;若连本地持久化也不可用,就不能假装受理成功。

缓存兜底要携带生成时间和版本。当前时间减去快照时间超过业务上限时应拒绝或展示未知,而不是无限使用旧数据。假设允许旧 5 分钟,缓存已 18 分钟,即使读取成功也不符合退化契约。

{
  "status": "DEGRADED",
  "dataVersion": 1842,
  "generatedAt": "2026-09-30T10:00:00Z",
  "staleSeconds": 47
}

五、恢复比进入退化更危险

依赖刚恢复时,大量请求、缓存回源和积压任务会同时涌入,容易形成二次冲击。恢复应先做探测流量,再限速回放积压,逐步扩大在线流量,并持续观察错误率和资源水位。

假设故障 10 分钟积压 12 万个任务,正常新增 150 个/秒,消费者恢复后总能力 350 个/秒,净消化速度只有 200 个/秒,需要 600 秒才能清空。若全速回放使数据库过载,恢复会再次失败,因此回放速率应受下游容量控制。

退化期间若允许多处写入,恢复还要处理冲突和对账。不能只切回路由就宣布完成。

六、用户和调用方必须知道语义变化

退化响应应通过状态码、字段或响应头明确表达,例如 PENDING、stale=true 或可识别错误码。返回 200 但内容是默认值,会让上游把不确定结果写成业务事实,后续无法补偿。

面向用户的提示也要可行动:“系统繁忙”不如“订单已受理,结果确认中,请勿重复支付”。对机器调用方则应说明是否可重试、建议等待时间和幂等要求。

退化功能要保持可访问性和安全性。静态兜底页不能泄露内部错误,旧缓存也不能绕过权限撤销等高风险更新。

七、如何观测和演练退化模式

监控应包含当前模式、切换原因、持续时长、退化请求数、旧数据年龄、积压和恢复进度。模式标签要进入日志和 Trace,排障时才能区分正常响应与兜底响应。

演练要验证进入、持续和退出三个阶段:注入依赖超时,确认阈值触发且核心链路稳定;保持故障,确认数据新鲜度不越界;恢复依赖,确认限速追赶、对账完成且不会重复执行。

mode: DEGRADED_READ_ONLY
entered_reason: primary_db_unavailable
duration_seconds: 420
stale_read_p99_seconds: 52
pending_actions: 0
recovery_progress: 0%

八、常见误区与追问

  • 误区:退化就是捕获异常后返回空对象。 空对象可能被解释为真实业务结果,必须明确退化语义和来源。
  • 误区:依赖一恢复就能立即退出退化。 缓存回源和积压回放可能再次压垮依赖,需要恢复状态和逐步放量。
  • 误区:所有依赖故障都应失败开放。 权限、风控和资金等高风险场景通常应失败关闭。
  • 误区:只要有缓存就能做退化。 缓存必须有版本、新鲜度上限和权限边界,过旧数据可能比失败更危险。
  • 追问:自动切换还是人工切换? 高频、可验证且安全边界明确的场景可自动;高风险或难以逆转的模式需人工确认与双重保护。
  • 追问:退化期间的写请求怎么办? 拒绝、可靠记录为待处理或只允许安全子集,不能在无法持久化时返回成功。
  • 追问:如何避免模式抖动? 使用连续窗口、不同的进入/退出阈值、最短保持时间和恢复探测。

九、加强记忆

把退化模式记成“能力缩水、语义透明、状态可控、恢复有序”。先按业务不变量决定保什么和停什么,再用显式状态机控制进入与退出;退化数据必须带新鲜度和结果状态,恢复时限速追赶并对账。真正成熟的退化方案不仅能撑过故障,还能安全回到正常状态。