返回分布式系统与数据链路模块
Distributed Quality / Tutorial 19

稳定性、容灾与故障演练教程

从缓存局部故障继续扩大范围,证明商城在服务、网络、数据库和第三方异常下能够止损、恢复并保持资金数据正确。

9 个章节故障注入 + 恢复验证RTO / RPO / 证据链
01

先定义稳定性,而不是盲目拔服务

业务结果优先

一次完整演练闭环

稳态基线成功率与延迟
注入故障单一、可撤销
观察响应检测、隔离、降级
撤销恢复数据对账与复盘

商城故障矩阵

故障业务风险通过标准
订单服务宕机新订单无法创建摘除实例;健康实例承接;不产生半单
网络延迟与丢包超时、重复提交、重试风暴超时预算有效;幂等;重试有上限
数据库主从切换短暂写失败或读旧数据恢复在 RTO 内;无事务丢失
支付渠道失败已扣款但订单未确认对账与补偿可追踪,不重复扣款
对象存储不可用凭证上传失败核心交易不被非核心附件拖垮
稳定性不是“永不失败”,而是故障发生时影响范围可控、核心业务有明确退路、数据不被破坏,并能在承诺时间内恢复。
02

把演练写成可停止的实验

先准备再注入

演练前

  • 限定隔离测试环境、服务、流量和持续时间。
  • 确定稳态指标:下单成功率、重复扣款数、P99、消息积压。
  • 写明假设、注入方式、负责人和观察人。
  • 设置停止条件、回滚操作和数据清理方式。

演练后

  • 先撤销故障并确认资源恢复。
  • 对账订单、库存、支付和退款。
  • 保存指标、日志、Trace 与操作时间线。
  • 把暴露的问题转成缺陷、告警或自动化用例。
实验卡示意
hypothesis: 订单服务损失 1 个实例时,下单成功率仍 >= 99.5%
scope: staging / 10% test traffic / 10 minutes
abort: error_rate > 5% for 60s OR duplicate_payment > 0
recovery: remove fault -> wait healthy -> reconcile orders
03

演练服务宕机与实例摘除

无半单、可接管

用例:当一个订单实例突然宕机时,健康实例应接管请求

  1. 预热固定测试流量并记录实例分布。
  2. 只终止一个测试实例,保持其余依赖不变。
  3. 观察健康检查、负载均衡摘除时间和错误率。
  4. 对超时请求使用同一幂等键重试。
  5. 核对订单、库存预占和支付单,确认没有重复或半成品。
  6. 恢复实例,确认不会一次性消费过期任务造成尖峰。

故障响应时间线

检测

健康检查识别异常

隔离

流量停止进入坏实例

接管

健康实例处理新请求

恢复

补偿并回到稳态

04

注入网络延迟、抖动与丢包

验证超时预算

网络故障用例

用例标题注入断言
当库存接口延迟 800ms 时,订单服务应在预算内失败或降级延迟 + 抖动超时边界明确,不无限等待
当支付回调响应丢失时,渠道重试不应重复扣款响应丢包同一回调幂等,订单最终一致
当消息链路间歇丢包时,事件应重试并可追踪10% 丢包无静默丢失,超限进入死信并告警
Toxiproxy 示例(隔离环境)
toxiproxy-cli toxic add inventory   --type latency --attribute latency=800 --attribute jitter=100
toxiproxy-cli toxic remove inventory -n latency_downstream
超时、重试和熔断要作为组合测试。单看重试成功率,可能掩盖重试风暴对下游造成的二次伤害。
05

验证数据库主从切换

事务与时间窗口

先定义两个目标

  • RTO:从数据库不可用到商城恢复可接受服务的最长时间。
  • RPO:切换后允许丢失的数据时间窗口;订单与支付通常要求接近零。

用例:当主库失效并切换到新主库时,已确认订单不应丢失

  1. 持续创建带 run_id 的订单并记录提交时间。
  2. 在授权的测试集群触发主库故障。
  3. 观察连接重建、写入失败和只读窗口。
  4. 恢复后按订单号对账数据库、库存和支付流水。
  5. 检查旧主库回归时不会产生双主写入。

切换验收

检查点证据
可用性错误开始与恢复时间,计算实际 RTO
数据完整性切换前后业务键连续,无已确认事务丢失
一致性读写分离不会长期读到旧订单状态
运维动作告警、切换、回切和负责人时间线完整
06

控制第三方支付与物流失败

不能控制依赖也能测试

支付未知结果的处理

支付请求携带幂等键
渠道超时结果未知
主动查询按流水号确认
补偿对账更新订单或退款

用例:当支付渠道超时但实际扣款成功时,系统应通过查询或对账确认结果

  • 使用可编程 Stub 返回超时,同时写入“渠道成功”状态。
  • 禁止客户端无新幂等键重复发起支付。
  • 验证查询、回调或对账任务把订单推进到 PAID。
  • 若超过业务期限,验证自动退款且退款只发生一次。
  • 报告必须关联 orderNo、paymentNo、channelNo 与 traceId。
07

验证限流、熔断、降级与恢复

保护核心交易

分级保护策略

能力商城例子测试重点
限流活动入口限制瞬时请求返回可识别状态;不误伤支付回调
熔断库存依赖持续失败后快速失败阈值、半开探测、恢复正确
降级暂时关闭推荐与评价核心下单仍可用;页面明确提示
排队秒杀请求进入有界队列队列满时快速拒绝;不超卖
恢复依赖正常后逐步放量避免同时重试形成恢复风暴

用例标题示例

当库存服务连续失败触发熔断时,商城应停止无效调用,并在半开探测成功后逐步恢复。

08

用真实恢复证明备份可用

备份存在不等于能恢复

备份恢复演练步骤

  1. 选取隔离恢复环境,记录备份版本、时间点、加密和保留策略。
  2. 恢复数据库与必要对象存储,不覆盖当前环境。
  3. 执行结构校验、行数与控制总额对账。
  4. 抽取订单—支付—退款链路做业务级验证。
  5. 测量实际 RTO/RPO,检查密钥、权限和应用连接。
  6. 销毁临时恢复环境前保存脱敏证据。
业务对账示意
SELECT COUNT(*) AS orders, SUM(pay_amount) AS paid
FROM orders
WHERE created_at < :restore_point;

-- 与支付流水控制总额、退款累计金额交叉核对
不要用“备份任务成功”替代恢复测试。只有把备份恢复成可运行、可查询、业务关系正确的数据,才证明恢复能力存在。
09

完成一次可审计的故障演练

练习与清单

练习

  1. 为商城交易链列出服务、网络、数据库和第三方四类故障。
  2. 为每类故障写稳态指标、注入方式、停止条件和恢复步骤。
  3. 执行一次单实例宕机和一次 800ms 延迟实验。
  4. 完成订单、库存、支付、退款对账并计算 RTO/RPO。
  5. 写复盘:假设是否成立,哪道防线失效,下次如何自动验证。

安全

  • 范围隔离
  • 操作可撤销
  • 停止条件明确
  • 负责人在线

证据

  • 基线已保存
  • 指标日志 Trace 齐全
  • 业务 ID 可串联
  • 恢复时间可计算

收尾

  • 故障已撤销
  • 数据已对账
  • 资源回到基线
  • 改进项有负责人