P14

多区域架构

点击正文段落选定收藏或划线位置;未选定时使用屏幕内第一段。

课内目录

1 多区域架构要回答什么

零售订单 API 已经能够接收下单请求、查询订单状态,并与库存、支付服务交换结果。现在业务准备服务相距较远的顾客,同时要求某个区域发生故障时仍能保留核心能力。架构图上增加另一个区域并不困难,困难在于解释:顾客的订单由哪里受理,写入成功究竟意味着什么,原区域不可达后谁有权继续修改,以及恢复后怎样处理尚未同步的数据。这些问题共同构成多区域架构的起点。

本课始终使用同一个案例:零售商在区域 A 与区域 B 部署订单 API,订单包含订单号、所属区域、商品摘要、状态及支付引用。订单状态从待支付进入已支付或已取消,库存扣减与支付处理由各自服务负责,订单服务只记录约定的业务结果。顾客可能刷新页面、重试提交或在旅行时切换网络,因此请求到达哪个入口,并不天然决定订单归谁管理。后续各章也沿用这个订单 API,不随技术主题更换业务假设。

先把需求写成可讨论的句子。例如,订单查询的目标是月度可用性达到 99.9%,本地区域正常时响应时间的第 95 百分位不超过 300 ms;区域中断后,核心查询希望在 10 分钟内恢复;已经确认受理的订单可容忍丢失多少,必须由业务另行批准。这里的数值是练习假设,不是行业承诺。恢复时间目标称为 RTO,恢复点目标称为 RPO,后者描述可接受的数据恢复缺口,常用时间范围表达。它们需要按下单、查询等能力分别约定。

多区域通常服务于距离、业务边界或故障隔离,但这几个目标可能相互拉扯。让顾客就近读取能缩短网络往返,要求每次写入都等待远端确认却会增加延迟;允许每个区域独立下单能减轻远端故障的影响,却需要明确库存如何分配。方案应先写出最关键的目标与允许降级的能力,再选择部署方式。不要把“全球低延迟、任何故障无损、所有区域随时写入”合并成一个没有条件的承诺。

订单 API 的区域、订单归属与数据路径
订单 API 的区域、订单归属与数据路径

图中区域 A 与区域 B 都能处理请求,但订单写入有明确归属。顾客就近访问,查询可以使用符合新鲜度要求的副本,修改则交给有权处理该订单的区域。这个安排不是唯一答案,却能把入口、业务权限与数据复制分开讨论。阅读后面的方案时,始终追问同一个问题:当前成功响应,是哪个区域凭什么证据给出的。

2 区域、可用区与流量入口

区域是具有地理边界和独立基础设施安排的部署范围,可用区是区域内部用于隔离部分故障的部署单元。把 API 副本放在同一区域的 2 个可用区,可以应对部分机房或实例故障;把系统放到 2 个区域,则可能进一步应对区域级中断。隔离程度取决于实际依赖,不能只数地图上的图标。若两边都依赖同一个身份服务、证书更新通道或数据库入口,这些公共依赖仍可能同时影响它们。

流量通常先经过域名解析或全局入口,再到区域入口,最后进入 API 实例。域名解析帮助客户端找到地址,却不会逐次检查每笔订单应由谁处理。客户端和中间解析器还可能缓存结果,因此调整解析记录并不代表所有顾客立即换路。全局入口可以依据健康状态和策略分流,但健康探测看到的只是指定探测路径。能够返回健康页面,不等于能够安全受理订单,更不等于库存和支付依赖正常。

对订单 API,应区分“把连接送到可用区域”和“授权该区域修改订单”。前者属于入口路由,后者属于业务与数据策略。某个顾客的请求进入区域 B,如果目标订单归区域 A 管理,B 可以把请求转发给 A,也可以返回明确的暂不可修改状态。不能因为入口切换了,就让 B 自动成为这笔订单的新写入者。否则顾客重试可能让两个区域分别接受相互矛盾的修改。

常见起点有 3 种:单区域运行并在远端准备恢复环境;主区域写入、其他区域提供受限查询;按顾客或订单归属划分写入责任,各区域处理自己的订单。它们不是按先进程度排列的等级。恢复环境通常建设较简单,但切换需要时间;远端查询改善访问体验,却引入数据新鲜度问题;分区写入能增强自治,但需要处理跨区域业务。选择应由需求和团队运行能力共同约束。

入口策略还应考虑容量。区域 A 平时承担 60% 的请求,区域 B 承担 40%,不代表 B 能在 A 故障时承接全部业务。是否预留容量、扩容需要多久、哪些接口优先保留,都应写清楚。对本例,可以优先保障已确认订单的查询,限制昂贵的历史搜索,并暂缓无法安全完成的新订单。入口切换只有与数据权限、依赖状态和承接容量相匹配,才会产生可用的业务服务。

3 数据驻留与跨区域延迟

数据驻留回答“哪些数据允许存放和处理在什么位置”。订单里的收货地址、联系电话与支付引用,未必具有相同的地域约束。不能因为订单主表留在区域 A,就认定整个系统满足驻留要求;查询副本、备份、日志、链路追踪、导出的分析文件都可能携带相同信息。方案需要建立数据类别与允许区域的对应关系,并由负责业务与合规的人员确认具体要求,架构图只负责准确表达已经确认的边界。

先做字段拆分往往比整体复制更容易控制。区域 B 的客服界面可能只需要订单号、状态、预计发货时间,而不需要完整地址。可以把允许跨区域的状态摘要复制到 B,将受限字段保留在所属区域,通过受控流程访问。这里仍要检查摘要是否能间接识别个人,以及访问日志是否重新记录了受限内容。最小化复制能减少传输和治理负担,但不能自动代替访问授权与保留期限管理。

跨区域延迟来自实际网络往返与处理链。假设客户端到区域 B 的往返约为 30 ms,B 到 A 的往返约为 90 ms,A 内部查询与排队共需 40 ms,那么经 B 转发到 A 的查询大约需要 160 ms,再叠加入口处理和响应体传输。这只是简化预算,不是严格预测。若查询订单后还串行访问 A 的另一个接口,就可能额外增加远端往返。应根据调用关系累加必要等待,而不是把所有跨区域访问都算作一次固定开销。

复制可以把读取留在本地,却带来新鲜度选择。异步复制允许 A 先响应,再把变化送到 B;此时顾客刚完成支付,在 B 可能短暂看到待支付。同步确认要求写入等待约定的远端证据,通常增加延迟,也让远端不可达影响写入完成。具体保证取决于系统配置,本课只讨论业务含义:成功时确认了哪些副本,远端断开时是否继续接受写入,以及读取允许落后多久。

跨区域查询、就近副本与订单版本证据
跨区域查询、就近副本与订单版本证据

订单页面可以显示数据更新时间,并对刚发生修改的会话优先读取所属区域。这样改善“刚写完却看不到”的体验,但会话信息可能丢失,顾客也可能换设备,所以不能把它当成所有读请求的全局一致保证。对于订单是否已经支付等关键判断,应由具备权威状态的服务完成,不能让浏览器凭一个可能滞后的页面决定再次扣款。读取策略必须与业务后果一起评估。

4 动手:对照一次跨区域读路径

本次练习不要求真实部署多个区域。准备同一笔测试订单 O-1401 的两份响应:区域 A 返回版本 18、状态已支付,区域 B 返回版本 17、状态待支付。设置场景为 A 刚处理支付结果,复制尚未追上。测试身份只允许读取该订单,样例字段不含真实顾客信息。目标是对照证据,理解不同读路径的行为,而不是从单次响应推断整个系统可靠性。

先设计 3 条路径:直接向 A 查询;进入 B 后由 B 转发到 A;直接读取 B 的本地副本。每条路径都记录入口区域、实际读区域、订单版本、业务更新时间、接口耗时和请求标识。请求标识用于关联同一次调用,不能代替订单版本。版本表达的是这笔订单的更新次序,时间戳用于辅助判断新鲜度;若两边时钟没有足够可信的同步,不应只靠时间戳判断谁更新。

按动画推进时,先在 A 读取版本 18,再观察 B 本地仍返回版本 17,最后等待复制完成,确认 B 也返回版本 18。把每一步的“请求成功”与“结果足够新”分开记录。HTTP 成功只说明服务器按当前接口语义给出了响应,不能单独证明数据符合订单页面的新鲜度要求。如果接口允许陈旧读取,应通过响应元数据或产品提示表达这种语义,避免调用方把所有成功响应都当成最新事实。

可以用下表填写模拟或真实实验结果。耗时为演示值,实际环境应测量多个时间窗口,包含正常负载与复制受阻的情况。

读路径实际读取位置返回版本示例耗时业务解释
直接读 AA 的权威数据18140 ms已看到支付结果
B 转发至 AA 的权威数据18170 ms较新,但增加远端等待
读 B 本地副本B 的查询副本1745 ms较快,仍显示待支付
复制追平后读 BB 的查询副本1845 ms此次已经追上

接着模拟 A 到 B 的复制暂停,让入口和 API 仍正常。预期现象是 B 的请求耗时可能没有明显增加,但版本停留在 17。这说明只看接口可用性和延迟,容易漏掉业务数据问题。应记录最近成功应用的订单变化位置,或使用持续更新的测试标记观察端到端滞后;单纯“最近没有收到消息”无法区分没有新订单与复制已经中断。生产环境的探测还要控制权限与测试数据清理。

从入口、读来源到复制新鲜度的观察链
从入口、读来源到复制新鲜度的观察链

最后写出实验结论:订单列表允许在约定范围内落后时,可采用 B 本地读取;顾客刚支付后的确认页优先读取 A,若 A 不可达则显示状态确认中并避免诱导重复付款。这里的选择取决于页面语义,不是按响应速度排名。一次实验只能证明给定条件下的路径行为,不能证明所有故障场景。保留请求与版本证据,才能让下一次演练与本次结果比较。

5 全局一致与分区自治取舍

全局一致在本课中指各区域按照约定看到协调后的业务状态,分区自治指某个区域在无法联系其他区域时,仍能在明确边界内处理业务。两者都需要具体到操作。订单查询可以允许状态短暂滞后,取消已发货订单却必须遵守状态规则;商品介绍可以从本地副本读取,最后 1 件商品的出售则需要避免重复承诺。不能把整个系统简单贴上“强一致”或“最终一致”的标签后就结束设计。

网络分区是区域之间无法正常通信的情形,即使两边 API 与数据库都在运行,也可能发生。若业务要求任何区域都立刻知道最新修改,那么通信中断时,某些请求就必须等待或失败;若允许区域继续独立处理,就必须限制其权限,或接受并处理事后差异。这个约束不是配置按钮造成的,而是双方暂时无法交换信息。具体协议如何达成一致留到后续课程,本课重点是把中断期间允许的行为写清楚。

本例可以按订单归属提供自治:A 创建的订单由 A 推进状态,B 创建的订单由 B 推进状态,跨区域只复制允许传播的摘要。同一笔订单通常只有一个区域负责写入,这降低了状态冲突。顾客来到另一个区域,订单归属仍保持不变。若确需变更归属,应采用有记录的交接过程,明确旧区域何时失去写入权、新区域何时取得写入权,而不是根据当前入口临时决定。

库存则需要额外约定。假设某商品共有 100 件,可事先分配 A 的可售额度为 60 件、B 为 40 件。网络中断时,各区域只在本地额度内接受订单,就能在此简化模型下限制超卖风险;代价是 A 用完额度后,即使 B 还有库存,A 也可能无法继续承诺销售。额度调拨需要可靠记录,不能由两边分别猜测。实际库存还涉及仓库变化与退货,本课只用额度例子说明自治需要预先划定资源边界。

滑块把允许的副本滞后阈值从严格推向宽松,观察本地读取比例与新鲜度风险怎样变化。它表达的是一种读策略:副本落后超过阈值时转向所属区域,所属区域不可达时按页面规则降级。滑块不会改变网络距离,也不会凭空让复制变快。支付确认等关键操作不能因为用户把阈值调大就采用陈旧状态,交互中的这些操作始终保留单独的业务规则。

可以将选择整理成决策记录,即 ADR。记录要包含背景、备选方案、决定与后果。例如,本阶段采用按订单归属写入加异步摘要复制,放弃“所有区域任意修改同一订单”;原因是先保障区域内处理的可解释性,团队暂不承担跨区域冲突解决的复杂度。后果包括远端订单修改依赖所属区域、切换前必须核对数据缺口。这些限制不是附注,而是业务负责人需要接受的方案组成部分。

6 常见坑:把多区域当自动容灾

最常见的错误是把流量改到 B 就宣布恢复完成。此时 B 可能只有旧副本,也可能没有支付回调配置、所需密钥或足够容量。若 B 允许修改,而 A 其实仍在运行,只是探测链路中断,两个区域就可能同时推进同一笔订单。故障切换必须同时回答流量去哪、数据是否满足要求、谁有写入权。仅有入口健康探测不能回答后面的问题。

自动切换可以缩短操作时间,但先要明确触发条件与保护措施。至少需要区分某个实例失败、区域入口不可达、关键依赖不可用,以及区域之间通信中断。健康探测最好从多个观察位置收集业务相关证据,仍需承认误判可能。对于订单写入,必须有防止旧写入者继续工作的隔离措施,常称为隔离旧主或撤销旧写权限。具体实现依赖数据系统,本课只要求方案证明权限不会重叠。

动画中的关键停点是“无法确认 A 已失去写入权”。此时 B 可以继续提供符合新鲜度规则的查询,却不应自动接管 A 的订单写入。业务可能选择暂停部分修改,换取避免重复受理或状态分叉。若能够通过可靠机制确认旧权限已撤销,再核对 B 的恢复位置与业务批准的 RPO,才进入受控接管。不要用“多等 30 秒”替代权限与数据证据。

另一个错误是把备份、复制和容灾混为一谈。复制有助于把变化送到远端,也可能快速传播误删;备份能保留历史恢复点,却不保证立即可以对外服务;容灾还需要恢复应用、权限、依赖与流量。对于订单,恢复完成后还可能需要核对支付渠道已成功但订单未更新的记录。恢复演练应验证业务闭环,而不只验证数据库能够启动。数据丢失风险应按照已经向顾客确认的业务结果来评估。

切回原区域同样是变更。若 B 在接管期间产生新订单状态,A 恢复后不能直接重新接收写入。需要确认复制方向、核对差异、安排写入权交接,并在观察窗口内检查重复事件与状态异常。回切可以延后到低风险窗口,不必与故障恢复同时进行。演练记录应包含触发证据、每个决策时间、影响订单范围和最终核对结果,这些材料才能支撑下一次缩短恢复时间。

区域故障时从证据到受控接管的排查路径
区域故障时从证据到受控接管的排查路径

7 案例:全局锁拖垮区域自治

团队最初选择按区域受理订单,宣称 A 与 B 可以独立工作。为了避免重复提交,又引入位于 A 的全局锁服务:任何区域创建订单前,都要先取得顾客购物车对应的锁。正常时 B 的调用多一次远端往返,仍能勉强满足响应目标。架构评审只看到了 B 有 API 和数据库副本,没有沿着下单请求检查这次取锁依赖,于是把部署独立误认为业务独立。

某次 A 与 B 之间的网络发生抖动。B 的 CPU、内存与数据库都正常,健康检查仍返回成功,但下单请求大量等待锁超时。客户端重试进一步增加排队,查询接口也受到共享连接池占满的影响。入口继续把顾客送到 B,结果是一个看起来健康的区域无法受理订单。故障证据显示,耗时集中在远端取锁步骤,复制滞后只是伴随现象,并不是此次下单停顿的直接原因。

修复前,团队先明确锁究竟保护什么。避免同一次提交产生重复订单,可以让客户端提供稳定的幂等键,并在所属区域把幂等记录与订单创建可靠地关联起来;重试到达其他区域时,应按同样规则找到所属区域。幂等键需要作用范围、有效期和相同键不同请求内容的处理规则,不能只给请求加一个随机字符串。若每次重试都生成新键,系统仍会把它们当作不同订单。

但幂等不能解决所有共享资源问题。防止全球库存超卖仍需库存责任划分或协调,不能删除锁后就声称风险消失。团队因此把订单创建的重复抑制放回所属区域,把库存承诺限制在预分配额度内。涉及跨区域合并购物车或额度调拨的操作暂时返回稍后处理。跨区域报表使用摘要副本,并显示更新时间。这样才能把区域自治落在具体业务边界上,而不是依靠“最终会同步”来解释所有差异。

新的 ADR 记录了代价:B 不再为每笔本地订单等待 A 的全局锁,但远端所属订单仍可能无法修改;本地额度耗尽时可能损失部分销售机会;幂等记录的保留与清理成为运行责任。团队通过注入区域间超时进行演练,观察 B 的本地创建成功率、重试重复率和查询延迟,并核对订单与库存记录。证据表明本地路径已解除该远端依赖,才能把“区域自治”写入可用性说明。

8 把区域策略写进部署方案

部署方案需要把区域策略变成可以执行与检查的约定。首先列出操作矩阵:本地订单查询、本地订单创建、远端订单查询、远端订单修改,分别标明入口、数据来源、写入权限、依赖与降级行为。其次列出数据矩阵:订单状态摘要可以去哪里,地址字段留在哪里,备份与日志如何遵守同样边界。矩阵不必复杂,但每一项都应能找到负责团队和验证方式。

备选方案至少比较当前需求下可行的路径。本例可以比较远端恢复环境、主区域写入加远端查询、按订单归属写入 3 种安排。比较维度包括正常延迟、区域故障时可保留的能力、恢复缺口、运行复杂度与成本。不要只给选中方案写优点。若业务只要求数小时内恢复,准备充分的恢复环境可能已经足够;若两地长期都有大量顾客,分区写入的收益才更可能覆盖额外投入。

成本应拆成常态与故障期间。常态包括 API 与数据副本、复制传输、全局入口、日志存储、备份和演练的人力;故障期间包括承接区域扩容、重放积压任务与业务核对。例如每月有 1000 万次订单变化,每次允许复制的摘要平均为 2 KB,单向复制原始载荷约为 20 GB,实际计费量还受协议、重试和计费单位影响。这只是复制量估算,不能当成总成本;跨区域查询返回的内容也要另计。

高可用评估应检查整条业务路径。API 多副本、区域入口冗余和数据库复制只是组成部分,身份校验、支付回调、库存服务、证书及操作权限也要进入依赖表。对于每个关键依赖,写明它失效时哪些能力继续、哪些能力停止,以及是否存在可验证的替代路径。尤其注意管理操作是否必须经过故障区域,否则即使 B 的服务资源齐全,值班人员也可能无法执行接管。

上线可以分阶段进行:先建立远端摘要查询与观测,再小范围启用 B 的本地订单归属,最后演练通信中断和区域接管。每阶段设定进入与退出条件,例如副本新鲜度持续满足约定、跨区域字段检查通过、重复提交核对完成。发布顺序还要考虑版本兼容,避免 A 产生的新状态被 B 的旧程序误解。多区域提高了发布与恢复的协调要求,这部分必须进入工期,而不能只估算资源创建时间。

9 从多区域架构走向扩展性模式(P15)

多区域解决了部署边界与故障边界的问题,但不直接回答业务增长后怎样增加处理能力。若每笔订单都经过同一个库存热点或共享数据库,新增区域可能只是让更多请求排队等候同一个资源。即使区域划分合理,单个区域内部也会遇到连接数、写入吞吐、队列积压和热点顾客等限制。下一课的扩展性模式将沿着这条订单链继续分析,而不是重新引入另一个业务案例。

进入 P15 前,应先保留本课形成的边界:订单归属决定修改权限,读取路径决定新鲜度语义,资源额度决定自治范围,故障策略决定哪些业务可以降级。扩展时可以增加 API 实例、划分处理队列或重新安排数据,但不能无意中破坏这些约定。例如缓存能减少查询压力,却可能增加状态陈旧;增加消费者能提高处理速度,却需要继续控制重复事件与订单状态推进规则。

容量目标也要与故障目标放在一起讨论。假设正常高峰为每秒 200 次创建请求,A 与 B 各自承担一部分;如果要求任意区域故障后仍保持全部创建能力,就必须证明幸存区域的计算、数据与依赖容量能够承接相应负载。若只承诺优先保障查询并限制新订单,则需要明确限流顺序与用户提示。不要把正常负载下的扩容演示,当成区域故障时的容量保证。

本课留下的交付物应能够交给另一位工程师继续设计:需求与验收指标、区域和依赖图、读取路径对照记录、ADR、成本假设,以及恢复操作与演练结果。它们共同描述当前能力的边界。P15 将在这些边界内讨论如何扩展吞吐与容量,并观察扩展动作是否引入新的共享瓶颈。先明确哪里允许独立工作,再决定哪里需要更多资源,扩展方案才有可以检验的基础。

放进方案里

在零售订单 API 的部署方案中,增加“区域策略”段落:区域 A 与区域 B 分别承接本地订单,订单创建时确定所属区域,后续状态修改由所属区域负责。允许跨区域的状态摘要异步复制,地址等受限字段按已确认的数据驻留规则保存,日志、备份和导出遵守相同边界。普通订单列表可使用满足新鲜度阈值的本地副本;支付后的确认页优先访问所属区域,无法确认时显示处理中,并保持重试幂等。

把验收目标按操作分别填写。正常情况下,记录查询第 95 百分位延迟与副本滞后;区域故障时,记录核心查询的 RTO,以及接管订单写入所允许的 RPO。入口切换前检查承接容量、数据恢复位置和写入权限,无法确认旧区域权限已撤销时,暂停接管其订单修改。库存按预分配额度受理,额度耗尽时限制销售,跨区域调拨另走受控流程。每项阈值由业务与运行团队共同确认。

用 ADR 比较远端恢复环境、主区域写入和按归属写入,说明本阶段选择及其限制。成本表包含常驻副本、复制与查询传输、入口、观测、备份、演练人力和故障扩容,标出订单量、摘要大小与预留容量等假设。依赖表覆盖身份、支付、库存及管理入口,逐项写出失效后的行为。上线先验证远端读取,再逐步开放本地创建,演练区域间通信中断与旧区域恢复。保存请求标识、订单版本、切换时间和业务核对结果,作为方案验收证据,并约定回切负责人及停止条件。

验收时增加双向隔离场景:阻断 A 与 B 的通信,但保留两地入口,验证同一订单不会被两地同时修改,本地库存额度不会被突破。恢复连接后,按订单版本核对积压事件,确认重复支付回调不会重复推进状态;保留两地响应与权限变更记录,任一项不符即停止扩大流量。

10 小结:下一步扩展性模式(P15)

多区域方案要同时说明请求入口、订单归属、数据驻留、复制新鲜度与故障接管权限。部署在多个地点只是起点,能够解释正常与中断期间的业务行为,才形成可执行的架构。

进入 P15 前,用 3 个问题检查本课方案:B 返回成功查询时,凭什么判断结果足够新?A 不可达时,谁能证明 B 有权修改其订单?幸存区域承接流量后,哪个共享依赖最先达到容量上限?带着这些证据继续讨论扩展性模式。

同阶段相关课

AI 答疑

默认关闭。启用后,只发送本课标题、最近阅读的屏幕内正文摘录(最多 6000 字)与本次问题。

配置自己的服务