1 为什么先学「高可用基础模式」
零售网站的商品页还能打开,顾客点击“提交订单”却持续转圈。此时首页的在线率再高,也不能证明订单服务可用。学习高可用,首先要把“机器还在运行”换成“顾客能在约定时间内完成约定动作”。本课围绕创建订单 API:顾客提交购物车、收货信息和请求标识,系统检查库存、保存订单,再返回订单号。支付只作为后续依赖出现,不在本课展开支付协议。
订单链路同时依赖入口、应用实例、库存服务和订单数据库。任何必要环节失效,都可能让顾客无法下单。高可用基础模式的价值,是在故障发生时保留足够的服务能力,并让恢复过程可预测。它通常包含冗余、健康检查、故障隔离、超时、受控重试和恢复验证。这些机制能够迁移到不同运行环境,重点不是购买哪种产品,而是理解故障发生后谁检测、谁决策、谁执行、谁确认。
假设活动期间每分钟有 6000 次创建订单请求,某个应用进程退出。若入口及时停止向它发送新请求,其余实例有足够容量,顾客可能只遇到短暂波动。若所有实例共用已经耗尽的数据库连接池,增加应用副本也不能解决问题。相同的“请求失败”,需要不同的故障模型。学会先画链路、再找共享依赖,比直接增加副本更接近真实问题。
还要明确高可用的代价。备用实例占用资源,探测消耗请求,跨故障域部署增加通信与运维复杂度,严格的数据保护可能增加响应时间。入门阶段不追求所有故障下都零中断,而是说明要覆盖哪些常见故障、允许多长中断、允许丢失多少已确认数据,以及如何证明方案符合这些约束。没有边界的“永不宕机”无法验收。
本课先把应用进程退出、实例变慢和单个故障域不可用作为主要情景。故障域是可能因共同原因同时失效的资源范围,例如同 1 台宿主机上的进程、同 1 机架的设备,或同 1 可用区的设施。不同可用区也可能共用网络、配置或操作流程。划分故障域的依据是共同失效原因,不能只看部署名称是否不同。

2 核心概念与边界
可用性描述服务在规定范围内满足约定的程度。用时间计算时,可以写成“可用时间 ÷ 约定服务时间”;用请求计算时,可以写成“合格请求数 ÷ 纳入统计的请求数”。两者不能混用。订单 API 更适合先定义请求口径:业务上有效的创建请求,在 1 秒内得到确定的创建结果或明确的库存不足结果,才算符合本课的服务约定。认证失败、非法参数是否进入分母,应事先写清,不能故障后再调整口径。
HTTP 状态码不能独自决定业务是否可用。返回 200 但没有保存订单,不算成功;库存确实不足而返回明确拒绝,可以算服务正常处理;返回“稍后再试”虽然比一直等待更友好,也没有满足创建订单的承诺。方案可以同时报告技术错误率、业务结果分布和端到端延迟,避免用其中某项替代全部体验。对订单成功还要定义持久性:返回成功后,系统应能够查询到相同订单,而不是只在应用内存中留下记录。
服务目标是事先约定的衡量标准。若示例目标为每月 99.9% 的请求符合约定,意味着仍有 0.1% 的请求余量,不能把它解释为每次故障都可以持续固定时长。按时间口径,30 天的 0.1% 约为 43.2 分钟;按请求口径,流量高峰的短故障可能消耗更多余量。设定目标时还要规定统计窗口、观察入口和维护期间的处理方式。本课数字用于说明方法,不代表所有订单系统都应该采用同样目标。
恢复时间目标 RTO表达发生指定灾难后,业务希望在多长时间内恢复;恢复点目标 RPO表达恢复时最多允许丢失多长时间范围的数据。若示例 RTO 为 10 分钟、RPO 为 1 分钟,就要分别检查恢复步骤与数据复制能力。应用实例切换很快,不等于数据库满足 RPO;有备份,也不等于能在 RTO 内完成恢复。订单通常对已确认数据更敏感,目标必须结合数据承诺单独讨论。
高可用、备份和扩容相互支持,但解决的问题不同。冗余副本帮助继续服务,备份帮助从删除或损坏中找回历史数据,扩容帮助承接更多负载。错误配置可能同时传播到所有副本,复制也可能同步错误删除,因此冗余不能替代备份。扩容需要时间,且可能碰到数据库上限,也不能替代预留容量。理解这些边界,才能避免把某项能力当成万能保证。
本课不展开跨地域多写、分布式共识算法和复杂事务协议。对于数据库,只要求读者辨认写入角色、复制滞后、切换权限和数据恢复边界。基础方案可以使用成熟数据库提供的复制与故障切换能力,但仍要验证应用连接是否恢复、旧写入者是否被阻止继续写入,以及成功响应对应的数据是否符合承诺。
后续分工也先记清:云上可用区级主动-主动/主动-备用、负载均衡摘除收敛、脑裂与写入隔离的机制细节见 C43「高可用设计」;备份、快照与受限恢复验收见 C44;同城/异地拓扑与切换判据见 P13「容灾架构」。本课先把可迁移的基础模式与方案写法立住,避免用云产品名称代替故障后的检测、决策、执行与确认责任。
3 关键机制(可迁移)
冗余先解决“还有谁能接手”。 将订单应用部署为多个可独立工作的实例,入口按照既定规则分配流量。创建订单所需的持久状态应保存在适当的共享存储中,不能只依赖某个进程的内存。否则流量切到其他实例后,顾客的请求上下文就可能消失。这里的“应用无状态”不代表系统没有状态,而是关键状态不绑定在可随时替换的应用实例上。
副本还应分散到要防范的故障域。2 个进程放在同 1 台机器上,可以防部分进程故障,却防不住整机掉电。跨可用区部署能扩大隔离范围,但前提是另一组有能力承接流量,且入口与数据层不会一起坏。若平时总容量刚好够用,失去半数实例后即使路由切换正确,服务仍可能因过载失败。应按照失去目标故障域后的剩余容量来验收,而不是只清点副本数。各层主动-主动或主动-备用怎样配、负载均衡如何收敛,留给 C43 用云资源机制展开。
健康检查解决“现在该把流量交给谁”。 存活检查判断进程是否需要重启,就绪检查判断实例是否适合接收新请求。实例启动后还没有加载配置,可能存活却未就绪。某个可选推荐服务不可用时,订单应用仍可能就绪。若把所有远端依赖都放进存活检查,共享依赖短暂抖动就可能触发所有应用一起重启,把局部问题变成全链路中断。
探测需要在速度与误判之间取舍。例如每隔 2 秒探测,连续 3 次失败后摘除,可以过滤偶发失败,但从真实故障到摘除仍有等待。实际时间还受故障发生相位、单次探测超时、检查调度和路由传播影响。不能简单把间隔乘以次数当成保证值。恢复时也可要求连续成功若干次,再逐步恢复流量,避免实例在健康与不健康之间反复切换。
故障切换解决“如何把接手变成动作”。 入口摘除不健康实例,剩余实例接收新请求;已有请求可能成功、失败或结果未知。切换不能自动补回所有进行中的操作。应用关闭时应先停止接收新请求,等待有限时间让已有请求完成,再退出。这样可以减少发布或维护造成的中断,但等待也必须有上限,不能让已经卡死的请求无限拖住退出。

隔离解决“故障能扩散多远”。 为库存调用设置并发上限,为订单查询和订单创建保留适当的资源边界,可避免大量慢查询占满所有执行位置。连接池、工作队列和线程都不是无限资源。队列变长会增加等待时间,等待中的请求又继续占用内存和连接。必要时拒绝超出承载能力的请求,虽然降低了当时的成功比例,却有助于保护仍能完成的请求与恢复能力。
这些机制必须连在一起看:没有健康检查的副本可能一直接收失败请求;没有容量余量的摘除可能压垮剩余实例;没有隔离的重试可能扩大压力。设计时应写出完整控制链:由哪个探测点发现什么信号,达到什么条件触发什么动作,动作影响哪些新请求,恢复后怎样确认稳定。每个箭头都应该能够通过配置、指标或演练结果找到证据。
4 关键机制续:落到订单链路
顾客点击提交后,客户端发送创建请求,入口转给订单应用,应用调用库存服务并写入订单数据库。为了保持入门范围,先假设库存预留和订单保存已有明确的业务接口;跨服务原子性不由高可用机制自动提供。方案仍要定义“库存已预留但订单未完成”的补偿或对账路径。不能因为请求最终返回错误,就断言所有业务动作都没有发生。
超时是等待预算。 假设客户端允许等待 1500 毫秒,入口分给应用 1200 毫秒,应用需要为自身处理和返回预留空间,库存与数据库调用就不能各自随意等待 1200 毫秒。可以用示例预算理解:库存最多 300 毫秒,数据库最多 400 毫秒,其余预算留给排队、处理和网络。真实数值应来自测量。下游超时应受剩余截止时间约束,排队时间也要计入,不能每进入新环节就重新获得完整预算。
重试只适合被允许重复的操作。 连接建立失败与写入后响应丢失,表面上都可能呈现为超时,但业务含义不同。后者可能已经创建订单。若顾客或应用直接重发,系统可能创建重复订单、重复预留库存。创建 API 应接收稳定的幂等键,将该键与请求内容摘要、处理状态和最终结果关联;重复到达时返回已有结果或明确的处理中状态。不同内容复用同 1 键应被拒绝。
幂等记录与订单写入必须有一致的保护方式,例如在同 1 数据库事务内完成,并使用唯一约束防止并发创建重复记录。只在内存里记下“刚才处理过”,实例重启后就会失效;只先查询再插入,也挡不住并发请求。记录保留期至少要覆盖约定的重试与结果查询窗口,过期后的行为也必须明确。幂等能力通常只覆盖约定的接口范围,不自动消除外部库存或支付系统的重复副作用。

重试还应有次数上限、退避和随机抖动,并且受总截止时间限制。只对明确允许的暂时性失败进行重试,库存不足、参数错误和鉴权失败通常不应重试。如果客户端、入口和应用各重试多次,最下游的实际请求数可能成倍增加。指定主要重试层,传递请求标识,记录每次尝试,才能看清重试是否正在帮助恢复。
熔断与降级帮助停止无效消耗。 当库存接口持续失败时,可以暂时停止大部分调用,等待后仅放行少量试探请求。熔断不会修好库存,也不能把创建失败变成成功。商品推荐可关闭,订单确认页面可以晚些展示非关键附加信息;库存确认和订单持久化若属于创建承诺,就不能静默省略。所谓“先返回成功,稍后再保存”,会改变业务承诺,必须作为另一种业务模式重新设计与说明。
5 动手与命令/控制台直觉
动手应在隔离的练习环境进行,使用测试商品和测试订单,并事先记录恢复动作。准备 2 个订单应用实例 A、B,1 个入口和可观测的测试数据库。先明确要模拟的是应用进程退出,不是数据库损坏。为请求生成幂等键,保存请求起止时间、响应状态、订单号和尝试次数。负载要稳定且低于单实例验证过的容量,才能把路由切换问题与容量不足区分开。
下面是示意命令,地址和字段需替换成练习环境中的真实约定。固定幂等键用于验证同 1 次业务请求的重复提交;测试新的业务订单时需要换键。命令中的超时只控制客户端等待,不会撤销已经在服务器执行的数据库提交。
curl --max-time 2 -i \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: p11-demo-order-001' \
-d '{"sku":"demo-01","quantity":1}' \
https://orders.example.test/orders
先连续提交若干不同幂等键的请求,确认基线延迟和成功比例。随后在练习平台停止 A,观察入口何时将 A 标记为不健康、何时不再向 A 分配新请求,以及 B 的请求量、延迟与资源占用怎样变化。不要只截图最后“全部健康”的页面;故障发生、检测完成、路由变化、业务恢复这几个时间点才构成恢复过程。若入口不提供路由事件,可以通过实例访问日志和请求标识辅助定位。
再用同 1 幂等键重复提交完全相同的请求,检查返回的订单号是否一致,并核对数据库中对应的业务订单数量。若出现超时,应先按接口约定查询该键的处理结果。练习环境可以提供按幂等键查询的接口,实际路径由系统定义;不能假设所有服务都天然支持。查询暂时找不到记录时,也要考虑读副本滞后,优先使用能提供所需一致性的结果查询路径。
接着恢复 A,观察启动、就绪、加入入口和流量增加的顺序。如果 A 尚未完成初始化就接到订单,说明就绪条件过早;如果恢复瞬间延迟陡升,可能需要预热或渐进增加流量。最后停止故障注入,确认实例数、路由、测试数据和临时限制均回到约定状态。练习完成的标准是观察到预期业务行为,并能解释差异,而不是仅完成停止与启动操作。
在控制台中,看到“运行中”要继续查看就绪状态与探测原因;看到“副本数 2”要查看是否分散在目标故障域;看到“自动切换成功”要核对应用是否已重新连接,并验证订单数据。命令与控制台都是观察和操作入口,真正的验收对象仍然是请求结果、恢复时间和数据承诺。对于数据库角色切换,应使用平台支持的演练流程,避免手工强制产生多个可写节点。

6 观测:看哪些字段与信号
观测首先围绕业务入口组织。创建订单 API 至少需要请求量、合格请求比例、错误分类和延迟分布。平均延迟可能掩盖部分顾客的长时间等待,因此还应观察 p95、p99 等分位数。p99 为 900 毫秒,表示统计样本中约 99% 的请求延迟不超过该值,不能说明所有请求都足够快。看图时同时查看样本量、时间窗口和超时请求如何计入,避免低流量时误读分位数。
入口与实例侧的数据应能够对上。入口记录原始请求数和转发尝试数,应用记录收到的尝试与业务结果;二者不同可能来自重试、路由失败或统计口径差异。建议在日志中保留时间戳、request_id、trace_id、实例标识、故障域、接口、结果类别、状态码、总耗时、下游名称、下游耗时和重试序号。幂等键可以使用受控摘要关联,避免在日志中暴露顾客个人信息或支付凭据。
trace_id 用来串联某次调用链,幂等键用来识别同 1 次业务意图,两者用途不同。顾客再次提交相同订单意图时,可能产生新的追踪,但仍应使用相同幂等键。排查重复订单时,仅靠追踪标识可能漏掉跨请求的关联。系统还应记录幂等命中、处理中冲突和内容不一致等结果,以便判断重试是否被正确吸收。
实例健康指标可以包括可接流量实例数、探测失败原因、重启次数、连接池使用量、工作队列长度和资源使用率。数据库侧需要连接数、写入延迟、错误类别、复制滞后和角色变化。复制滞后的时间指标有实现差异,不能只凭某个瞬时值就承诺精确 RPO;还需结合提交位置、复制机制和恢复验证。容量告警应关注剩余可承载能力,而不只是某台机器是否达到固定使用率。

事件也属于证据。发布版本、配置修改、实例摘除、数据库切换、扩容开始与完成,都应带时间和作用范围。若延迟升高恰好发生在发布附近,只能形成调查线索,不能直接认定发布是根因。要继续查受影响实例、错误类型及回滚后的变化。统一时钟与明确时区能减少时间线误差;不同系统存在采集延迟时,需要在结论中保留不确定范围。
告警应能引导行动。例如“连续 5 分钟创建合格率低于目标”可以触发业务排查,“剩余就绪实例不足以覆盖目标流量”可以提示容错余量丢失。练习时区分业务已经受损和保护能力下降,避免让所有告警都表达同样严重程度。告警附上接口、窗口、分母、主要错误类别和相关变更,值班人员才能判断应先恢复依赖、限制流量,还是回退有问题的发布。
7 常见坑与反模式
“有 2 个副本就高可用。” 如果副本共享同 1 台宿主机、同 1 份错误配置或同 1 个容量不足的依赖,故障仍可能同时发生。纠正方法是列出要覆盖的故障,再逐项标注副本分布、共享依赖和接手容量。应用副本数是设计输入,不能直接充当业务可用性的证明。还应确认入口本身不是未经保护的单点。
“探测越快越好。” 极短探测间隔和超时可能把网络抖动误判为故障,引发反复摘除。摘除后流量集中到剩余实例,又可能导致新一轮探测失败。探测路径应轻量、具有代表性,并结合连续失败阈值与恢复阈值。调整之前先观察探测耗时分布和误判情况,再评估检测速度是否值得增加不稳定性。
“失败就一直重试。” 持续过载时重试会占用本已不足的容量,令新请求也无法完成。设置总等待预算、最大尝试次数和退避,并对不同错误分类处理。重试预算还要跨调用层协调。对于结果未知的写请求,先依靠幂等与查询确定状态,不能通过增加尝试次数来替代正确性设计。
“把所有依赖纳入健康检查更安全。” 如果推荐服务变慢会让所有订单实例都被摘除,原本可通过关闭推荐维持的订单能力就消失了。应区分实例自身故障、关键依赖故障和可选依赖故障。共享数据库不可用时,让所有实例重启通常没有帮助;更合适的动作可能是限制请求、明确失败并保留恢复所需资源。
“切换成功等于业务恢复。” 管理页面可能只表示新数据库角色已选定,应用仍在使用失效连接,或者连接池没有清理旧连接。恢复验证要覆盖实际创建、按订单号查询和幂等重复提交,并观察一段稳定窗口。若发生数据角色切换,还要核对旧写入者被隔离,不能允许网络恢复后出现未经协调的双写。
“降级后把所有响应都算成功。” 排队页、稍后再试和订单已创建是不同业务结果,必须分别统计。如果引入异步受理模式,应返回可追踪的受理凭据,说明查询方式和最终结果时限,并重新定义服务目标。入门方案优先保持承诺清晰,避免靠更换状态码或隐藏错误来美化可用率。
8 案例:订单系统相关故障
某零售系统在活动前部署了 2 个订单应用实例,正常时分别承担约半数流量。团队曾用进程退出演练确认入口能够摘除故障实例,但没有在活动流量下验证剩余容量。活动开始后,A 因进程异常退出,入口很快停止向 A 转发,B 的请求量随之接近原来的 2 倍。页面显示仍有健康实例,创建订单的 p99 延迟却迅速升高。
B 的工作队列持续增长,数据库连接池接近上限。客户端遇到超时后立即重试,入口也启用了重试,实际调用尝试数进一步上升。数据库本身没有发生角色切换,但写入延迟受到连接竞争影响。故障由单实例退出触发,再被容量不足和多层重试放大。若只看到数据库慢,就可能误把下游症状当成最初原因,盲目增加应用副本还可能带来更多连接。
团队先限制入口接入量,让系统保留完成已有订单与查询状态的能力;暂停入口的额外重试,保留应用中已约定的有限重试策略。同时恢复 A,并确认它完成初始化后才加入流量。队列下降后,订单延迟逐渐恢复。处置时要持续对照业务成功比例,不能仅因资源使用率下降就撤销限制,否则积压请求与新流量可能再次把系统推过承载边界。
复盘时发现,部分顾客在超时后重新点击提交,客户端生成了新的幂等键。服务端虽然实现了按键去重,但无法识别这些请求属于相同业务意图。团队修改客户端流程,在同 1 次提交意图的重试与结果查询期间保持键稳定,同时保留“主动创建新订单”的明确入口。对于已经产生的重复订单,通过业务审核、库存释放和顾客沟通流程处理,不能简单删除数据库记录来掩盖影响。
整改分成几个可验收动作:在目标峰值下停止任意 1 个应用实例,验证剩余实例仍能满足创建目标;核对客户端、入口和应用的尝试次数上限;观察每秒原始请求与实际尝试之比;验证超时后的幂等查询;将单实例容量和数据库连接总预算写入部署规则。扩容策略仍可保留,但它承担流量增长的补充作用,故障发生后的即时承载能力由已经准备好的余量负责。
还可以用数据库切换作为后续演练情景。此时要增加复制滞后、应用连接恢复和数据核对证据,不能直接套用应用进程退出的验收结论。不同故障可能共用部分机制,但数据风险与恢复步骤并不相同。案例给出的可迁移经验是:先辨认触发故障,再辨认放大因素,最后分别验证止损动作和长期修复,避免把所有改进都归结为增加机器。
9 排查案例:证据链怎么写
现在把上述事故整理成其他人可以检查的排查记录。开头写明观察对象:创建订单 API、活动时间窗口、统计入口、有效请求定义和受影响用户范围。再描述现象,例如“从 14:02 起,创建请求超时比例上升,查询接口基本正常”。不要开篇就写“数据库故障”,因为这已经是原因判断。现象与结论分开,才能避免后续只寻找支持最初猜测的材料。
接着建立时间线。14:02:00,实例 A 退出;14:02:06,入口记录摘除 A;14:02:10,B 的接收请求量明显增加;14:02:20,B 的队列和连接等待上升;14:03 后,重试尝试数继续增长。这些时间是案例示例。实际记录必须说明来源,例如进程事件、入口路由日志、指标窗口和调用追踪;若指标按 1 分钟聚合,就不能声称凭它确定了秒级先后顺序。

然后提出竞争假设。假设 1 是库存服务故障,可检查库存延迟与错误是否先于订单异常;假设 2 是数据库主动切换,可查看角色事件、连接错误及复制状态;假设 3 是实例损失后的过载,可检查剩余实例请求量、排队时间、池等待和重试比例。这里不要求把所有可能性列完,而是对当前证据支持的主要解释给出可区分的检查办法。
证据链应连接“发生了什么”与“为何产生该影响”。A 退出说明容量减少,B 流量增加说明入口完成接手,队列增长与连接等待说明处理能力跟不上到达速度,尝试数增长说明重试正在增加负荷。数据库无角色变化只能削弱某个假设,不能单独证明数据库完全健康。若缺少故障前基线或关键日志,应明确记录证据缺口,并在后续演练补齐。
止损动作也要记录效果与边界。限制流量后,实际尝试数下降,队列开始收敛,创建延迟恢复,这支持过载是主要放大因素。限流期间被拒绝的请求仍要计入约定口径,不能从报告中消失。恢复 A 后,应观察是否重新分摊流量、是否出现重复订单以及是否有未完成库存预留。仅凭某条错误日志不再出现,不能宣布所有业务影响结束。
最后把结论写成“触发事件、放大机制、影响、恢复动作、预防验证”。例如:A 退出触发容量损失,剩余容量不足与多层重试放大排队,导致创建超时;通过限制流量、收敛重试和恢复实例止损。预防项要对应负责人、完成条件与演练方法。只有能再次执行并得到明确结果的检查,才是可验证的整改;“加强监控”“提升稳定性”本身还不足以关闭问题。
放进方案里
在零售订单方案中,把高可用写成可以验收的服务承诺。先确定创建订单的业务边界、有效请求口径、统计窗口与延迟要求,区分创建成功、库存不足、暂时拒绝和结果未知。明确已返回成功的订单必须能够查询,并将数据恢复目标与服务恢复目标分别记录,避免用应用在线率替代业务可用性。
部署描述应给出入口、应用实例和订单存储的职责,标注副本所在故障域以及仍然共享的依赖。容量以失去目标故障域后能承接的有效请求量为依据,同时列出数据库连接与库存并发预算。说明哪些故障由平台自动切换,哪些需要人工处置,人工步骤从什么告警开始、由谁执行、怎样回退。
请求保护部分写明总等待预算、关键依赖超时、主要重试层、最大尝试次数及退避方式。创建接口使用稳定幂等键,记录与订单写入采用一致保护,并提供结果未知时的查询路径。可选能力可以降级,库存确认与订单持久化仍遵守原有承诺;若业务选择异步受理,应单独说明最终结果时限。
验收覆盖应用退出、依赖变慢和受控数据库切换等约定情景,逐项保存故障时间、检测时间、路由变化、恢复时间和数据核对结果。观测材料包含业务合格率、延迟分布、尝试次数、就绪容量、连接等待与复制状态,并关联发布和配置事件。演练结束还要确认临时限流、故障注入和测试数据已清理。
交付时附上剩余风险与适用条件,例如跨可用区共享依赖仍可能同时失效,备份恢复需要另行验证(见后续 C44),流量超过验证范围时需要重新评估容量;云上多可用区接管与写入隔离的机制验收见后续 C43,异地切换架构见后续 P13。成本说明对应备用资源、观测和演练投入。用这些材料回答“能覆盖什么、怎样恢复、如何证明”,使高可用从架构图上的副本数量变成可执行、可复核的方案。
10 小结:检查清单
- 是否从顾客动作定义可用性,并明确分母、窗口与延迟要求?
- 是否区分服务恢复目标与数据恢复目标,写清已确认订单的承诺?
- 副本是否跨越目标故障域,剩余容量是否经过负载验证?
- 存活、就绪、摘除和恢复条件是否各有明确作用?
- 超时是否服从总预算,重试是否有限并有退避?
- 创建请求是否具备持久幂等保护与结果查询路径?
- 关键依赖与可选功能是否有清晰边界,降级是否诚实表达结果?
- 是否能用请求、实例、依赖和变更事件串起证据链?
- 是否通过实际请求验证恢复,并检查重复订单与遗留库存预留?
- 演练结果、剩余风险、恢复责任与回退步骤是否能够交给其他人执行?
下一课转向 P12 方案设计入门练习:把本章验收过的结论带进后续主题,写成可检查的方案约束。