1复合故障现场
林薇(化名)团队三年前按主备加冷备库完成同城双活,标称 RPO 十五分钟、RTO 三十分钟。今年大促前华东机房断网演练时,复合场景接连暴露:GSLB 权重切到华南后,订单服务仍大量连接华东 Redis;MySQL 半同步复制 lag 八分钟,切主后会员余额出现双写冲突;运维 Runbook 里的一键切换实际依赖六个手工步骤,第四步 SSH 超时,演练四十七分钟业务才恢复,超过 SLA 三倍。
09:12 网络值班:核心交换机 BGP 抖动,跨 AZ 丢包约百分之十二,华东入口错误率上升。
09:18 OnCall 执行 GSLB 权重百分之一百华南;DNS TTL 六十秒,客户端仍缓存华东 VIP,App 硬编码华东域名。
09:26 DBA:半同步复制 lag 达八分钟,存储 redo flush 延迟;尝试 promote 后出现会员余额双写冲突。
09:35 运维 Runbook 第四步需 SSH 华东堡垒机,因分区超时卡死;业务全断直至 09:59 才恢复,RTO 四十七分钟。
复盘会上,DBA 说复制 lag 是存储 IO 毛刺,网络说 GSLB 已切流,开发说代码没写多活路由。三方陈述均为事实,但同步、调度、切换三条链路各自建设、缺少统一状态机,等于没有多活。林薇重读凤凰架构容灾章节时注意到:作者把异地多活与异地容灾区分,前者要求常态下双中心同时承接流量,后者允许备中心空闲;无论哪种,工程核心都是数据怎么一致、流量怎么定向、故障怎么切,而非机房数量。
本篇用架构师视角建立入口现场、三柱机制、一致性 RTO 验证、演练检查表沉淀闭环。文中 GSLB、Binlog 同步、单元化路由表等名称仅作映射示例,决策逻辑与具体厂商无关,银行单元化、电商两地三中心、物流多 Region 均可复用同一套不变量。性能与时长数字若无特别标注,均为合成演练示例,用于说明量级与排障顺序,不代表任何单一客户现场。
复合故障的可怕之处不在于单点技术难,而在于观测面分裂:入口监控显示华南流量上升,应用层错误率仍指向华东依赖超时,数据库面板显示从库 lag 曲线平台化,而业务方只看到下单失败率飙升。没有跨层关联 ID 与单元标签,值班工程师会在三个控制台之间往返,每一层都觉得自己已执行预案,整体却仍在恶化窗口内。
| 时间 | 动作 | 预期 | 实际 |
|---|---|---|---|
| T+0 | 华东 AZ 网络分区 | 自动降级 | 跨 AZ RPC 重试放大 |
| T+6 min | GSLB 切华南 | 入口脱离故障域 | App 仍连华东 Redis |
| T+14 min | 尝试 promote | lag 小于 30 s | lag 8 min 双写冲突 |
| T+35 min | Runbook SSH | 脚本完成切换 | 堡垒机不可达 |
林薇团队在 T 加五至 T 加二十回放时发现:若组合执行 GSLB 与服务注册联动权重清零华东、应用路由表强制 cell 等于 cn-south、数据库只读门禁华东主并待 lag 小于三十秒再 promote,业务可在十五分钟内以只读加延迟写有损恢复,而非四十七分钟全断。缺失的不是机房,而是三柱联动编排。后续章节分别展开机制,并用 RPO RTO 矩阵说明为何只读有损往往是正确权衡。
GSLB 只解决入口 DNS 或七层,服务发现、数据库连接串、缓存拓扑、消息集群若仍指向故障域,切流等于空转。有从库就能切主、无单元化约束的全局双写、演练通过等于生产可用——四类误判在林薇演练中全部命中。
1.2 现场四类误判
- 「GSLB 切了就是多活」:GSLB 只解决入口,服务发现、DB 连接串、缓存拓扑、消息集群仍指向故障域则切流空转;
- 「有从库就能切主」:半同步在 IO 毛刺时 lag 不可控;promote 前未执行 lag、GTID 连续性、冲突表门禁,必然双写;
- 「多活 = 双写双读」:无单元化约束的全局双写,冲突成本指数上升;凤凰架构推荐按业务键分片,每单元写本地、跨单元异步;
- 「演练通过 = 生产可用」:Runbook 依赖故障域 SSH,分区时控制面自我不可用——自动化必须控制面与数据面分离。
1.3 架构师前十分钟:三问定调
OnCall 前 10 分钟不要 promote,先回答:调度——用户流量、服务注册、长连接、定时任务是否已全部离开故障域?同步——各存储 lag、未同步事务、缓存脏数据窗口是否小于 RPO?切换——下一步是否依赖故障域网络?顺序是否断写 → 追平 → 切主 → 开写 → 验证?
1.4 五层失序叠加
| 层次 | 设计预期 | 演练实际 | 后果 |
|---|---|---|---|
| L1 入口 | GSLB 与单元状态联动 | 仅手工改 GSLB | 流量部分仍入华东 |
| L2 应用 | 单元路由 + zone 感知 | Nacos 华东仍 UP | RPC 跨故障 AZ |
| L3 数据 | 半同步 + promote 门禁 | lag 8 min 仍升主 | 订单号、余额冲突 |
| L4 中间件 | Redis/MQ 与 DB 同序切换 | Redis 双写、offset 未冻结 | Session 丢失、重复消费 |
| L5 运维 | 异地编排、可审计 DAG | SSH 依赖华东堡垒机 | T+35 min 脚本卡死 |
1.5 OnCall 禁止事项
- 禁止未 isolation 直接 promote——故障域可能仍在接收写;
- 禁止仅改 GSLB 不改 DB 连接串与缓存拓扑;
- 禁止从故障域内发起切换脚本;
- 禁止同时重启南北两中心——易双主;
- 禁止跳过对账开全量写——应优先核心链路 + 只读兜底。
林薇 T+22 min 同时操作 Redis 主从切换与 Kafka consumer reset,无编排顺序,offset 回退导致支付回调重复——典型「抢恢复」反模式。
1.6 黄金窗口与容灾假阳性
回放显示 T+5~T+20 min 若执行预案组合:GSLB + 服务注册联动权重清零华东;应用路由表强制 cell=cn-south;数据库只读门禁华东主、待 lag < 30 s 再 promote——业务可在 15 分钟内以只读 + 延迟写有损恢复。凤凰架构称之为「容灾假阳性」:纸面 RTO 30 分钟,演练 RTO 47 分钟,且产生数据不一致。最昂贵的架构债是「华南机房建了、库同步了、GSLB 配了」,但应用层无 Cell/Unit 路由——多活评审必问:任意请求从进入到落库,能否画出当前活跃单元与写入权威副本?
版本说明:本文模式层与语言无关,示例基于 GSLB、MySQL 8.x 半同步、Nacos 2.x 与自研单元路由表。性能数字若无特别说明均为合成示例,机制描述以《凤凰架构》容灾章节与 MySQL 官方复制文档为准。阅读前提:你已理解 RPO/RTO、主从复制与服务发现;本文不再解释「什么是异地容灾」,而是聚焦三柱在复合故障窗口如何耦合。
2凤凰架构中的多活谱系与三柱
凤凰架构将大型分布式系统的可靠性讨论从单机可用性提升到业务连续性。异地多活在谱系上位于同城双活与冷备之间:比冷备更接近常态分担,比单活同城更强调跨城网络不确定性。架构师应先问业务能否接受跨城读写延迟与冲突解决成本,再选模式,而不是先买第三个机房。
三柱模型把多活从口号翻译成可验收能力。数据同步柱回答丢失窗口与冲突边界;流量调度柱回答请求与写入落在哪里;故障切换柱回答状态如何从常态走到隔离、只读、升主、开流、验证。三柱必须由同一单元状态驱动,否则会出现 GSLB 已切而数据库仍写故障域的经典分裂。
三柱不是三个项目,是一条状态机。《凤凰架构》将大型系统可靠性分为进程内容错、集群内容错、地域间容错——异地多活处于最高层。数据同步定义 RPO 下界;流量调度定义常态与故障态请求去向;故障切换定义 RTO 上界与验证。三柱必须同一套元数据驱动:例如单元 cn-east-1 状态 = ISOLATED 同时触发 GSLB 权重 0、Nacos 下线、DB 只读、编排暂停向东写入。林薇失败于三柱各用各的配置源,无统一状态。
每个核心服务维护 Region 依赖矩阵:对象存储、统一登录、支付渠道、风控、配置中心、密钥管理。切换时必须标注故障域依赖不可用时的降级策略。林薇演练中对象存储仍在华东,华南订单无法上传凭证——调度柱已切、同步柱未覆盖非 DB 资产,属设计遗漏。
多活谱系常见分层包括:主备热备、同城双活、两地三中心、单元化多活、全局多活。每一层对网络 RTT、数据分片、运维编排的要求非线性上升。林薇团队当时停留在热备加半同步,却用 GSLB 做了入口分担,属于调度超前、同步与切换滞后,演练必然击穿 SLA。
| 模式 | 常态流量 | RPO 量级 | 适用约束 |
|---|---|---|---|
| 主备热备 | 单中心 | 分钟级 | 研发规模有限 |
| 同城双活 | 双中心分担 | 秒级 | 低 RTT 光纤 |
| 两地三中心 | 主中心+异地 | 秒到分钟 | 监管容灾 |
| 单元化多活 | 多 cell 并行 | 按单元定义 | 超大规模分区 |
评审多活方案时,建议用不变量清单代替组件清单:任意写请求能否指出权威副本;任意读请求能否指出允许陈旧度;任意切换步骤能否指出可逆操作与审计记录;任意依赖能否指出故障域外降级路径。组件可以替换,不变量不能丢。
《凤凰架构:构建可靠的大型分布式系统》明确区分异地多活(常态双中心同时承接流量)与异地容灾(备中心可空闲),并强调失败设计与业务连续性目标先于组件堆叠。具体 RPO/RTO 数字仍需结合企业监管与组件能力重新测算,不可直接套用本书或厂商白皮书中的示例值。
2.2 与同城冷备的本质差异
同城冷备切换通常只需:停主 → 升备 → 改 VIP → 启应用。异地多活额外增加:常态双写或双读(从 A 活+B 活到 B 主+A 隔离);跨域依赖(对象存储、统一认证须故障域外降级);合规审计(切换脚本本身要异地部署、多活可用)。凤凰架构将 Region 级响应定义为预编排的宏观状态迁移,而非 OnCall 临场创意。
2.3 架构评审五问(多活专用)
- 核心域是否单元化?分片键与跨单元调用清单是否签字?
- 同步柱 RPO 取最慢层(DB / Cache / MQ / OSS)是否计算?
- 切换 DAG 是否完全不依赖故障域 SSH / API?
- promote 前硬门禁条件是否与业务 RPO 一致?
- 上次演练 RTO/RPO 实测值是否 attached 在架构评审单?
3数据同步柱:RPO 工程
数据同步柱的工程目标是可证明的 RPO,而不是复制链路存在。半同步、异步 Binlog、逻辑复制、CDC 到 Kafka 再落地,每种技术对应不同的故障窗口与运维复杂度。架构师要把 lag 分布、promote 条件、冲突检测策略写进切换状态机,而不是写在 DBA 个人文档里。
林薇案例 lag 八分钟的根因链是:存储 redo flush 延迟放大、跨 AZ 带宽争抢、从库回放单线程瓶颈,三者叠加在演练流量尖刺下形成平台。若只有平均值监控而无 P99 lag 与字节滞后双指标,OnCall 会在 lag 已不可接受时仍执行 promote,导致余额双写冲突。
| 复制形态 | RPO 直觉 | 切换风险 | 运维要点 |
|---|---|---|---|
| 异步 Binlog | 秒到分钟 | promote 丢窗口 | lag P99 告警 |
| 半同步 | 秒级 | 主库写入阻塞 | 从库健康探针 |
| CDC 到 MQ 再落地 | 可配置 | 消费位点 | 幂等与顺序 |
| 对象跨区复制 | 分钟级 | 凭证上传失败 | 依赖矩阵单行 |
冲突解决策略必须在设计期选型:最后写入胜出、版本向量、业务补偿、冻结账户人工核对。没有策略的 promote 等于把一致性债务转嫁给客服与财务。凤凰架构强调失败设计,同步柱的失败窗口应产品化:哪些交易可自动重试,哪些必须阻断并提示。
3.2 同步策略谱系
| 模式 | 典型实现 | RPO 量级 | 适用 |
|---|---|---|---|
| 异步复制 | MySQL 异步从、Redis 主从 | 秒~分钟 | 日志、非核心读模型 |
| 半同步 / quorum | MySQL semi-sync | 0~数秒 | 订单、账户核心库 |
| 单元内单写 + 跨单元异步 | 按 userId 分片;CDC / 消息 | 业务定义窗口 | 电商、物流大流量多活 |
| CRDT / 冲突合并 | 购物车、点赞计数 | 语义层最终一致 | 可合并域,非账务 |
不变量:promote 前必须满足 lag < RPO_threshold 且 GTID / binlog 位点连续;否则选择只读有损或延迟切换,而非强行升主。林薇 lag 8 分钟仍 promote,违反不变量。
3.3 DB 以外的「隐形 RPO」
搜索引擎 Canal 到 ES、配置中心 Nacos 多集群同步、KMS 跨 Region 复制——同步路径往往慢于 DB。配置也是状态:南北 Feature Flag 不一致会引发行为分裂;KMS 延迟导致 JWT 验签失败,表现为「切换后全员登出」。RPO 取各层最大值,依赖矩阵每一行标注 RPO 与切换动作。
缓存与消息常被忽视:Redis 跨 Region 若双主需分片键约束或接受会话重建;Kafka MirrorMaker consumer offset 与切换顺序绑定。林薇演练中华南订单无法上传凭证,因对象存储仍在华东——同步柱评审范围常窄于 MySQL。备份与复制不是一回事:备份解决逻辑错误或勒索恢复;复制解决机房丢失。半同步在单 AZ 存储抖动时可能阻塞主库写入,这是为 RPO 买的延迟税,架构师须向业务解释而非隐藏。
4流量调度柱:单元化
流量调度柱定义常态与故障态请求去哪。单元化把用户、商户或地理范围绑定到 cell,使切换变成 cell 状态变更而非全局脑裂。GSLB 只覆盖入口 DNS 或七层权重,服务发现、客户端 SDK、消息消费位点、批处理调度都必须纳入调度柱,否则入口已空转。
林薇 App 硬编码华东域名属于客户端调度缺失。更隐蔽的是支付回调 URL 仍注册华东公网地址,GSLB 切流后支付成功但订单状态不更新。调度柱交付物应包含全链路 URL 与连接串清单,并能在演练中一键校验指向活跃 cell。
单元化路由
- 切换粒度清晰,可逐 cell 隔离
- 冲突面随分片缩小
- 与注册中心联动自然
仅 GSLB 权重
- 客户端与服务发现易粘滞
- 数据库与缓存仍双写
- RTO 不可证明
服务发现 zone 感知是调度柱中枢。Nacos 或 Eureka 中华东实例仍 UP 时,Feign 默认轮询会把 RPC 打回故障 AZ。权重清零必须与注册中心 API 联动,不能依赖工程师手工点控制台。合成示例:联动 API 延迟三十秒,仍优于 DNS TTL 六十秒加硬编码域名叠加的分钟级错误。
单元路由表应存在于网关、BFF 与核心写服务三层,且由同一配置源版本化发布。只改网关不改订单服务,会出现头信息指向华南而 JDBC 仍连华东的撕裂。配置发布应支持演练模式:只读注入新路由而不开写,验证读路径正确后再进入切换状态机。
Stateful 组件是调度柱盲区:WebSocket 长连接、SSE、有状态网关、本地队列消费者。HTTP 无状态服务切 GSLB 相对简单,长连接需连接迁移或强制断连重连策略,并在用户侧可接受范围内设计重连退避,避免重连风暴打穿存活机房。
4.2 单元化核心规则
- 分片键:userId、merchantId、orderId 等确定默认单元;
- 本单元读写:同单元内 DB、缓存、消息闭环;跨单元走异步或只读副本;
- 调度层:GSLB 地理就近 + 单元健康;网关解析分片键路由;
- 容灾调度:故障单元用户临时迁移到备单元,非全量双写。
| 调度层 | 常态职责 | 切换时动作 |
|---|---|---|
| GSLB / DNS | 地理就近、权重分担 | 故障域权重 → 0;低 TTL + 客户端多域名 |
| API Gateway | 分片键解析、单元路由 | 拒绝 ISOLATED 单元;503 + Retry-After |
| 服务发现 | 同单元实例注册 | 故障域实例批量下线 |
| 定时任务 | 按单元分片执行 | 暂停故障域 job;防双跑 |
4.3 长连接与有状态服务
| 类型 | 风险 | 调度策略 |
|---|---|---|
| WebSocket / 推送 | 连接粘滞故障域 | 地域亲和 + 故障时 disconnect + 客户端重连备域 |
| gRPC 长连接 | Channel 缓存旧地址 | 短 TTL + 健康检查失败触发 channel 重建 |
| 移动端 SDK | 内置 Host 列表 | Remote Config 下发机房列表;演练验证强制刷新 |
| 第三方支付回调 | 回调 URL 指向故障域 | 多 URL 注册或网关统一入口 |
林薇 App 硬编码华东域名属于移动端调度缺失;支付回调 URL 仍注册华东公网 IP 则 GSLB 切流后支付成功但订单状态不更新——须在依赖矩阵单独一行标注。
大促前常做单元封网与路由冻结。任何入口变更必须同一变更单包含注册中心权重、网关路由版本、核心 JDBC 与 Redis 拓扑三项,缺一项则拒绝发布——避免「头信息华南、JDBC 仍华东」的撕裂。
5故障切换柱:状态机
故障切换柱把 Runbook 手工步骤产品化为可审计 DAG。节点类型包括:隔离、只读门禁、复制追平检查、promote、Traffic ON、业务验证、回滚。每个节点有前置条件、超时、失败分支与负责人角色,SSH 到堡垒机不应是唯一执行通道。
林薇 Runbook 第四步依赖华东堡垒机 SSH,网络分区后直接卡死,说明切换柱与故障域耦合。编排器应部署在第三站点或双活运维平面,使用带外网络与 API 驱动云厂商、GSLB、数据库运维接口。人工审批可以在环,执行必须自动化。
状态机建议最少五态:HEALTHY、DEGRADED、ISOLATED、READONLY_GLOBAL、AUTHORITY_SHIFTED。林薇案例缺少 ISOLATED 与 READONLY 的强制门禁,导致 GSLB 切了仍写华东 Redis。状态变更应写入不可篡改审计日志,供监管与复盘使用。
| 状态 | 调度柱动作 | 同步柱动作 | 切换柱动作 |
|---|---|---|---|
| ISOLATED | GSLB 权重清零 | 停写故障域 | 审计记录 |
| READONLY | 开读华南 | 追平 lag | 阻断 promote |
| AUTHORITY | 路由权威 cell | promote 完成 | 幂等校验 |
| TRAFFIC_ON | 开写 | 冲突队列空 | 业务探活 |
promote 不是按钮美学,而是条件集合:lag 小于阈值、复制线程健康、从库只读、冲突队列清空、下游消息冻结完成。任一条件不满足应停在 READONLY 而非强行开写。
5.2 切换八步状态机
- DETECT:多源确认,避免抖动误切;
- ISOLATE:故障域断写——DB 只读、消息 producer 停、缓存拒绝写;
- DRAIN:在途请求排空;长连接 Graceful 关闭;
- VERIFY_SYNC:备域 lag、位点、冲突检测;不满足则 DEGRADED 只读;
- PROMOTE:DB 升主、Redis 主从、MQ 领导选举;
- TRAFFIC_ON:GSLB + 发现 + 路由表开写;
- VALIDATE:合成探测、核心链路拨测、对账任务;
- ROLLBACK or STABLE:失败回滚;成功记录基线。
控制面异地部署:编排器、Runbook 执行器必须在非故障域可达。林薇 T+35 min SSH 卡死,根因是控制面与数据面同域。推荐分级自动化:自动隔离 → 人工确认 promote → 自动验证;金融场景 promote 可加双人复核,但复核界面须部署在异地控制面。
回切比切换更易出错:故障域恢复后若立即双写,可能旧数据覆盖新数据。回切不变量:备域继续 authoritative 直至故障域追平 lag;GSLB 权重渐进上调 10% → 50% → 100%,非一步切回。
6一致性与 RTO 权衡验证
一致性与 RTO 的权衡是多活设计的核心张力。更强一致性通常拉长切换时间与可用性窗口;更快 RTO 往往接受可量化数据丢失或服务降级。架构师应给出条件化结论:在 lag 小于 X 秒时目标 RTO 为 Y 分钟;在 lag 大于 X 时切换策略转为只读加延迟写,而非硬 promote。
验证方法包括:表格化 RPO RTO 目标与实测、故障注入与游戏日、混沌工程在单元边界的有限爆炸半径。林薇演练的价值在于暴露假设错误,而非通过演练。未通过的演练应产生工程变更单,而不是只更新 PPT。
只读有损恢复常被业务拒绝,直到用金额量化全断成本。合成示例:四十七分钟全断 versus 十五分钟只读,若峰值下单损失可估算,则产品可能接受短暂只读。架构师要把技术选项翻译成业务语言,而不是坚持理想多活。
双写冲突的检测应前置:切换前冻结写、切换中维护冲突表、切换后批量对账。会员余额类强一致域应使用单写 cell 加跨 cell 读,而不是双活双写同一行。凤凰架构对透明分布式事务的谨慎态度提醒:不要指望协议层掩盖错误的拓扑。
观测验证需要统一标签:cell、authority、role、drill_id。没有标签的指标无法证明三柱联动是否发生。建议在演练开始时生成 drill_id,贯穿日志、链路追踪、编排审计,避免事后无法对齐时间线。
6.5 CAP 的可操作翻译:RPO / RTO / RLO
网络分区发生时,一致性 C 与可用性 A 不可同时满足。工程上不做哲学讨论,做业务窗口签字:RPO 是可接受丢失的数据时间窗口;RTO 是可接受业务中断的上限;RLO 是恢复到什么能力——全功能、只读、核心链路。林薇 SLA 写 RTO 30 min / RPO 1 min,但 lag 8 min 仍 promote——验证层缺失,SLA 只是文档。
SLA 对齐方法:按域拆分 SLA(支付 RPO 0 / RTO 5 min;浏览 RPO 5 min / RTO 30 min);SLA 反推同步(RPO 1 min 则半同步 ack + 网络 RTT + 磁盘 flush 须 < 60 s);SLA 反推 RTO(RTO 15 min = 检测 2 + 隔离 3 + promote 5 + 验证 5,每段需监控 KPI)。架构师要对业务承诺可验证:每次 SLA 变更须附带最近一次演练实测 lag / RTO。
在 lag 不可追平窗口内,优先只读有损而非硬 promote,通常能缩短用户可感知中断时长;该推断依赖林薇回放与合成损失估算,落地前需用本业务峰值流量与对账成本做专项验证,不可直接套用 47 与 15 分钟两个数字。
6.2 业务场景权衡矩阵
| 业务场景 | 一致性 | 推荐同步 | RTO 策略 |
|---|---|---|---|
| 账户余额、支付 | 强一致 / 可审计 | 单元内单写 + 半同步 | 宁可 RTO 延长,也不 lag promote |
| 订单创建 | 因果一致 | 单元内事务;号段预分配 | 15 min 内单元级切换 |
| 商品浏览、搜索 | 最终一致 | 异步 + CDN | 分钟级;可 stale 读 |
| Session / 购物车 | 会话级 | 单元亲和或 JWT 无状态 | 5 min;可重建会话 |
6.3 RTO 分解:47 分钟如何优化
| 阶段 | 林薇演练耗时 | 优化手段 |
|---|---|---|
| 检测 + 决策 | 5 min | SLO 自动告警 + 预授权切换 |
| GSLB / DNS 生效 | 3~8 min | 低 TTL + 客户端多域名 |
| 服务发现与路由 | 10 min | 与 GSLB 联动 API |
| DB promote + 验证 | 12 min | 自动化 lag 门禁;并行非串行 |
| SSH 脚本卡死 | 7 min | 控制面异地;消除 SSH 依赖 |
优化目标:检测 2 min + 自动隔离 3 min + 有条件 promote 5 min + 验证 5 min ≈ 15 min。验证层不是「再测一遍」,而是把上表每一行变成演练 KPI。
6.4 与 T13 分布式事务的边界
跨单元强一致 2PC / TCC 在多活中慎用:跨 Region RT 与分区概率使 2PC 成为可用性杀手。推荐单元内本地事务 + 跨单元 Saga / 本地消息表;全局唯一性用号段 / Snowflake 带单元前缀。林薇订单号冲突,根因是双中心递增 ID 无单元前缀——属同步柱设计缺失。
切换后第二战场是对账:T+0 对账 Job 比对订单总量、支付总额、库存 delta;冲突表记录 promote 窗口双写嫌疑;幂等键全局唯一。林薇演练后花 6 小时手工对账 1400 条冲突订单,说明切换 SOP 缺对账自动化。
7工程化框架:DAG 与路由
工程化框架占本篇约一成篇幅,目标是把三柱落到可执行组件边界。切换不应是 6 个 SSH 步骤,而应是 idempotent 编排 DAG,部署在异地控制面。开源可映射 Temporal、Argo Workflows;自研需满足:每步可重试、可跳过、有 timeout、结构化日志供审计。
# 切换 DAG 片段 — 模式通用,非厂商绑定
name: region-failover-cn-east
steps:
- id: isolate_east
action: set_cell_state
params: { cell: cn-east, state: ISOLATED }
- id: gslb_drain
action: gslb_set_weight
params: { region: cn-east, weight: 0 }
depends_on: [isolate_east]
- id: verify_lag
action: assert_replication_lag
params: { max_seconds: 30, source: east, target: south }
- id: promote_south
action: mysql_promote
when: verify_lag.success
// 单元路由 — 与 Spring Cloud Gateway / 自研网关同构
public RouteTarget resolve(Request req) {
String shardKey = req.header("X-User-Id");
Cell cell = cellRegistry.locate(shardKey);
if (cell.state() == CellState.ISOLATED) {
throw new ServiceUnavailableException("cell isolated");
}
return cell.endpoint();
}
单元状态 ISOLATED 由切换编排写入,与 GSLB、Nacos 同源。生产级演练四门禁:网络分区(非仅改 GSLB)、存储 IO delay、控制面禁止从故障域发起、完整 reverse DAG 回切。
7.2 lag 门禁脚本与观测
# 切换前 lag 门禁 — 模式通用
LAG=$(mysql -h south-replica -e "SHOW REPLICA STATUS\G" | awk '/Seconds_Behind_Source/{print $2}')
RPO_MAX=30
if [ "$LAG" -gt "$RPO_MAX" ]; then
echo "BLOCK promote: lag=${LAG}s > RPO=${RPO_MAX}s"
exit 1
fi
指标名可按 Prometheus / 云监控调整;关键是 lag 与 RPO 比较结果进入 promote DAG 的 assert 节点,而非仅 Dashboard 给人看。架构评审五问与检查表应作为上线 gate,而非文档归档。
框架不是替代架构判断。单元划分错误、RPO 指标虚假、依赖矩阵缺失时,再优雅的 DAG 也只是快速失败。林薇团队应先补不变量与状态机,再选型编排引擎,顺序不能颠倒。
8决策矩阵
决策矩阵帮助在模式之间做条件化选择。主备适合 RPO 分钟级可接受且流量单中心;同城双活适合低延迟强一致域;两地三中心适合监管与地理容灾;单元化多活适合超大规模用户分区。没有银弹,只有约束下的最优。
| 场景 | 推荐模式 | 关键风险 | 不建议 |
|---|---|---|---|
| 强一致账户 | 单写 cell + 跨读 | 跨 cell 对账 | 双活双写同行 |
| 全国 C 端读多 | 单元化 + GSLB | 客户端粘滞 | 硬编码域名 |
| 监管两地三中心 | 主备 + 半同步 | RTO 分钟级 | 夸大 RTO 30 s |
| 物流多 Region | 数据分区多活 | 跨区依赖 | 全局单库 |
成本维度不仅含机房租金,还含研发维护单元路由、对账人力、演练停工与合规审计。林薇团队若早用矩阵评估,会发现半同步加硬编码域名与目标 RTO 三十分钟根本不匹配,应在架构评审门拦截而非大促前才演练。
技术选型与组织匹配:小团队优先简化拓扑与强 Runbook 自动化;大团队可投入平台组维护单元元数据与编排。矩阵应有一列组织成熟度,否则技术正确而执行失败。
三柱联动得当
- 单元状态机驱动 GSLB + Nacos + DB 门禁
- lag 超阈自动只读,人工仅确认 promote
- 控制面异地,DAG 每步可审计
- 演练 KPI 与 SLA 文档对齐
林薇式分裂配置
- GSLB 切了但 JDBC 仍连故障域
- lag 8 min 仍 promote,产生双写冲突
- Runbook 依赖故障域 SSH
- 纸面 RTO 30 min,实测 47 min
8.2 两地三中心 vs 单元化多活
| 模式 | 流量 | 数据 | RTO/RPO 典型 |
|---|---|---|---|
| 同城双活 + 异地冷备 | 同城双中心分担 | 同城同步;异地异步 | RPO 分钟级;RTO 小时级 |
| 两地三中心(2+1) | 两活一灾备 | 主中心写;近同步 + 远异步 | RPO 秒~分钟;RTO 15~30 min |
| 单元化多活 | 多 Region 同时在线 | 单元内单写;跨单元异步 | RPO 业务定义;RTO 5~15 min |
选型不问「行业标杆怎么做」,而问:核心交易是否可单元化?若否,多活成本在跨单元事务(见 T13),RPO 很难低于异步复制下界。
9演练与观测
演练与观测是多活的免疫系统。季度演练应覆盖单柱失效与两柱同时失效,游戏日应包含业务方验收而不仅是基础设施切换成功。未通过的演练应产生工程变更单,而不是只更新 PPT——林薇演练的价值在于暴露假设错误,而非通过演练。
合成示例指标:GSLB 生效三到八分钟可通过低 TTL 与客户端多域名缩短;服务发现联动若手工 ten 分钟,应改为 API 分钟级。把组件 SLA 累加成端到端 RTO 预算,任何一步无预算则整体目标虚假。
OnCall playbooks 应与 DAG 节点一一对应,禁止游离 Wiki 步骤。观测除黄金指标外,必须监控 lag P99、单元状态分布、DAG 节点耗时、回调 URL 探活。
| 支柱 | 核心指标 | 告警含义 |
|---|---|---|
| 同步 | replication_lag_seconds、GTID gap | lag > RPO → 禁止 promote |
| 调度 | 各 Region QPS 权重、跨 Region RPC 比例 | 权重与状态不一致 → 联动失败 |
| 切换 | DAG step 耗时、上次演练 RTO | 单步 timeout → 编排故障 |
四门禁演练:网络分区 / IO 慢 / 控制面隔离 / 回切;季度无预告小流量。混沌实验须在 shadow 集群执行,shadow 需与生产同构配置,否则结论无法迁移。
9.2 演练级别与通过标准
| 级别 | 注入 | 通过标准 | 负责人 |
|---|---|---|---|
| L1 | 单 AZ 网络分区 | 单元隔离,其他 cell 正常 | 开发 |
| L2 | 分区 + 存储 IO delay | lag 门禁阻断 promote;只读有损恢复 | SRE |
| L3 | 全链路 + 大促峰值流量 | 核心 SLA 达标;T+0 对账无差额 | 架构委员会 |
Postmortem 必填字段:重试/双写放大估算、promote 窗口与冲突量、各阶段 RTO 实测、对账差额。与系列 T09 衔接:多活指标应进入统一 Grafana 大盘,与 DB lag、跨 Region RPC 比例同屏——单独 GSLB 绿点无法发现「权重 0 但 JDBC 仍写故障域」。
10检查表与延伸阅读
与系列 T07 衔接:Kafka MirrorMaker 多集群 consumer offset 须与 DB promote 顺序绑定;T10 可靠性四件套管单 Region 内雪崩截断,本篇管跨 Region 同时在线时的三域协同。T12 秒杀链路单元化后,库存扣减须在单元内闭环,禁止跨 Region 同步重试扣库存。
10.1 核心结论
带走三句话:第一,有备机房不等于多活,三柱须由统一单元状态机驱动。第二,lag 超阈时只读有损往往优于硬 promote。第三,切换控制面不能依赖故障域 SSH——林薇 47 分钟 RTO 的主因是分裂配置,而非单点网络故障。
组织面检查:是否有跨 DBA、网络、开发的单一值班指挥;是否有依赖矩阵 owner;是否有监管要求的切换审计保留期。技术完美而组织分裂,仍会重现林薇式 47 分钟——多活是工程能力,也是协作协议。
回到林薇案例:若在演练前落地单元状态机 + lag 门禁 + 异地编排 + GSLB 与 Nacos 联动,T+15 min 应进入 DEGRADED 只读而非错误 promote。多活目标不是永不故障,而是故障可预期、切换可验证、不一致可界定。
10.2 多活演练检查表
| 检查项 | 标准 | 责任人 |
|---|---|---|
| 单元化分片 | 核心交易有明确分片键;禁止无约束全局双写 | 架构 / 业务 |
| 单元状态机 | ACTIVE / DEGRADED / ISOLATED 驱动 GSLB、发现、DB 门禁 | 架构 / SRE |
| 同步 RPO 分层 | DB / Cache / MQ / OSS 分别定义 RPO;门禁取最慢层 lag | DBA / 中间件 |
| 流量全路径 | DNS、GSLB、Gateway、App 域名、长连接、定时任务纳入调度柱 | SRE / 开发 |
| 切换编排 DAG | idempotent 步骤;控制面异地;零依赖故障域 SSH | SRE |
| promote 硬门禁 | lag < RPO + GTID 连续;不满足自动只读 | DBA / SRE |
| 依赖矩阵 | 对象存储、认证、支付等跨 Region 依赖有降级策略 | 架构 |
| 全局 ID | 号段 / Snowflake 含单元前缀;切换后对账脚本就绪 | 开发 |
| 业务验证探针 | 切换后合成交易 + T+0 对账 + MQ lag,非单组件 ping | QA / SRE |
| 四门禁演练 | 网络分区 / IO 慢 / 控制面隔离 / 回切;季度无预告 | SRE |
| RTO/RPO 实测 | 最近演练实测值 attached 评审单 | SRE / 架构 |
| 回切 SOP | reverse DAG 测试通过;禁止故障域未追平开写 | SRE |
10.3 延伸阅读
- BOOK周志明《凤凰架构:构建可靠的大型分布式系统》— 容灾、服务容错与全局事务章节
- BOOKGoogle SRE Workbook — Failover 与 Disaster Recovery Testing
- DOCMySQL 8.x Replication — Semi-sync 与 GTID 故障切换官方文档
- SERIES同系列 T13《分布式事务选型》— 跨单元 Saga 与 RPO 衔接
- SERIES同系列 T07《Kafka 容灾》— MirrorMaker 与多活消息层
- SERIES同系列 T16《Spring Cloud Alibaba 落地》— Nacos 多集群与多 Region 注册