想象你正在规划一场四城跨年旅行:订机票、订酒店、买景区门票、订跨年餐厅。四件事分散在四家平台,没有谁能一口气全办妥。更麻烦的是,如果机票订好了,酒店却满房,这趟旅行还没出发就崩了。这时候你最希望系统做什么?自动把机票也退掉,让整趟计划干干净净回到原点。分布式系统里的 Saga 模式,干的就是这件事。 一个跨服务流程里,本地事务就像一个个孤立的预订,谁也管不了谁。Saga 的思路很朴素:先把每站订好,每站配一条“后悔药”(补偿操作);中途某站失败,就沿来路一站站吃后悔药,把已生效的预订全部撤销。至于“谁来安排这一站接一站的动作”,业界有两种玩法:一种由总协调者拿着总行程单逐站指挥,叫编排式(Orchestration);一种没有头儿,每个服务完事就发通知给下一站接力,叫协同式(Choreography)。本文就借这场跨城旅行,把两种玩法的门道讲透。

岗位关联

掌握 Saga 两种实现方式的取舍,是设计可靠跨服务数据一致性的核心技能,也是微服务架构师与后端工程师面试的常见考点。

目录
  1. 可视化演示
  2. 1. 分布式事务困局
  3. 2. Saga 模式原理
  4. 3. 编排式实现
  5. 4. 协同式实现
  6. 5. 对比与选型
  7. 6. 落地实践
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示Saga模式通过本地事务链与补偿操作实现最终一致性,含编排式协调器与协同式事件驱动两种实现对比。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Saga正向事务链 每个服务执行本地事务并发布事件 正向链按顺序执行T1→T2→T3→T4 Saga = T1 + T2 + T3 + T4 Saga通过本地事务序列实现分布式最终一致性

1. 分布式事务困局

旅行计划的第一步,是搞清楚“为什么不能一个电话全搞定”。订机票找航空公司,订酒店找酒店集团,买门票找景区,订餐找餐馆——四家平台各管各的系统,数据库互不相通。这在分布式系统里叫“跨服务数据一致性”难题。

单体应用时代,一次操作几个表,一个数据库事务就能锁住全部数据。微服务化之后,数据被拆到不同服务的数据库里,本地事务只能管自己那一亩三分地。于是出现两条经典路线:2PC(两阶段提交)和最终一致性。Saga 属于后者。

2PC 的思路是“先问清楚再动手”:第一阶段所有参与者预提交,第二阶段协调者拍板提交或中止。它有两个硬伤:一是参与者全程锁资源同步等待,网络抖动就卡死一片;二是协调者单点,它一挂,所有参与者僵在半路。更底层地看,CAP 定理告诉我们:网络分区(P)不可避免,此时一致性(C)和可用性(A)只能二选一。2PC 押注了 C 牺牲了 A,所以才需要 Saga 这种“保 A 求最终 C”的路线。跨服务事务的失败概率还会随服务数量指数级上升:

这就像四家平台必须同时给你“有房有票有位”,一家的系统出问题,整个计划就得重排。2PC 是“先全锁住等我确认”,Saga 则是“先订着,不行就退”——后者显然更贴近真实世界。

P成功=∏i=1npi=p1×p2×⋯×pn\displaystyle P_{\text{成功}} = \prod_{i=1}^{n} p_i = p_1 \times p_2 \times \cdots \times p_n
服务越多,所有节点同时成功的概率越低——这正是分布式事务“天然难做”的数学直觉。
  1. 第 i 个节点成功率\(p_i\) 表示第 \(i\) 个微服务节点成功完成本地操作的概率,n 是参与本次跨服务流程的服务数量。
    pip_i
  2. 整体等于连乘\(\prod_{i=1}^{n} p_i\) 表示把 n 个概率依次相乘,也就是所有服务必须全部成功,整体才成功。
    ∏i=1npi\prod_{i=1}^{n}p_i
  3. 规模放大效应每个概率都小于 1,乘的项越多结果越小,服务一多,整体成功率断崖式下降。
    P成功=∏i=1npiP_{\text{成功}}=\prod_{i=1}^{n}p_i

2. Saga 模式原理

既然同步锁死行不通,Saga 换了个思路:先走起来,再留后手。你订机票时,航空公司告诉你“可免费退改”;订酒店时,平台写明“入住前 24 小时可取消”。这些退改政策,就是补偿操作的种子。

1987 年 Hector Garcia-Molina 提出 Saga 概念,2017 年前后在微服务工程实践中被发扬光大:把一个大型分布式事务拆成 n 个本地事务(T₁……Tₙ),每个本地事务配一个补偿操作(C₁……Cₙ)。全部成功则任务完成;某个 Tᵢ 失败,就逆序执行 Cᵢ₋₁……C₁,把已生效的副作用“补”回来。Saga 不保证全局强一致,只保证最终一致:过程可以呈现中间状态(机票已出、酒店未确认),但终态只有两种——“全部完成”或“全部补偿完成”。

关键设计点在于:每个 Tᵢ 和 Cᵢ 都是独立提交的本地事务,各自持久化,任何一步失败都可以通过重试恢复。整个 Saga 可以形式化为一组“正向-补偿”对:

行程单上每一站都写好了“后悔药配方”:机票可退、酒店可取消、门票可改签。出了问题不用重新规划,只要按反方向把药吃一遍,旅行计划就干干净净地回到原点。

Saga={(T1,C1),(T2,C2),…,(Tn,Cn)}\displaystyle Saga = \{ (T_1, C_1), (T_2, C_2), \ldots, (T_n, C_n) \}
一个 Saga 就是 n 对“前进动作 + 后悔药”的有序集合,顺序执行、逆序补偿。
  1. 正向事务\(T_i\) 是第 \(i\) 步的正常业务操作,比如“订机票扣款出票”,它必须是一个已提交的本地事务。
    TiT_i
  2. 配套补偿\(C_i\) 是与 \(T_i\) 成对的补偿操作,专门负责撤销 \(T_i\) 已产生的业务影响,比如退票退款。
    CiC_i
  3. 成对有序集合整个 Saga 是 n 对“正向-补偿”的有序组合,按 \(T_1 \to T_2 \to \cdots \to T_n\) 顺序执行,失败时按 \(C_{i-1} \to \cdots \to C_1\) 逆序补偿。
    Saga={(T1,C1),(T2,C2),…,(Tn,Cn)}Saga=\{(T_1,C_1),(T_2,C_2),\ldots,(T_n,C_n)\}

3. 编排式实现

编排式像跟团游:旅行社派出一位总导游,手里攥着完整行程单。导游先给航空公司打电话订票,收到“成功”答复后,再给酒店打电话……每个服务商只跟导游一个人对接,不需要知道其他服务商是谁。

编排式 Saga 的核心是一个中央协调器(Orchestrator)——通常是一个独立服务或状态机。协调器持有整个流程的状态,逐个调用各服务的本地事务接口,根据返回结果决定下一步:成功就调用下一个服务,失败就触发逆序补偿。所有服务被动执行,流程集中可见,日志从协调器一处就能串出全貌。

协调器的本质是一个状态机:当前状态 \(s_t\) 记录“走到哪一步”,收到服务返回的事件 \(e_t\) 后,状态转移函数算出新状态,决策函数再决定下发什么指令。这组关系可以写成:

导游打完一圈电话,每通都有明确答复:“行”或“不行”。不行?导游立刻翻出退改政策,火速打电话把前面几站全部取消。全程你只需要盯住导游一个人——这就是编排式“集中控制”的价值。

st+1=f(st,et),at=g(st)\displaystyle s_{t+1} = f(s_t, e_t), \qquad a_t = g(s_t)
协调器就像一本“行程账本”:记着当前到哪一站、收到什么回执、下一步该打哪个电话。
  1. 当前状态\(s_t\) 表示协调器在第 \(t\) 步所处的流程节点,例如“机票已订、待订酒店”。
    sts_t
  2. 事件输入\(e_t\) 是刚返回的结果事件,取值通常是成功或失败,例如“酒店确认”或“酒店满房”。
    ete_t
  3. 状态推进状态转移函数 \(f\) 把 \((s_t, e_t)\) 映射到下一个状态 \(s_{t+1}\),决定流程走到了哪。
    st+1=f(st,et)s_{t+1}=f(s_t,e_t)
  4. 决策下发决策函数 \(g\) 根据当前状态 \(s_t\) 算出动作 \(a_t\),即调用哪个服务、还是启动补偿流程。
    at=g(st)a_t=g(s_t)

4. 协同式实现

协同式则是自由行:没有导游,你订完机票,航空公司系统自动向酒店平台发一封“邮件”(事件):旅客航班已定,请预留房间。酒店确认后,又自动通知景区售票处……每一站只认识下一站,大家靠事件接力推进。

协同式 Saga 的核心是事件驱动与发布/订阅。每个服务完成自己的本地事务后,向消息总线发布一个领域事件(如“机票已出”);关心该事件的下游服务订阅并消费它,继续自己的本地事务。流程没有中央控制器,而是由一串事件自然串联。链条可以表示为:

协同式的最大优点是去中心化:没有单点故障,服务间松耦合,新增一个服务只需订阅相关事件。但代价是流程隐式化——全局状态藏在每个服务各自的事件日志里,想确认“旅行走到哪了”得把所有日志拼起来。接力棒一旦掉在地上(事件丢失),没人能一眼看出问题出在哪一棒。

Ti→发布事件 EiTi+1(i=1,2,…,n−1)\displaystyle T_i \xrightarrow{\text{发布事件 } E_i} T_{i+1} \quad (i = 1, 2, \ldots, n-1)
协同式没有“总导游”,每个服务独立决策、主动担当,靠事件把流程串成一条链。
  1. 本地完成\(T_i\) 表示第 \(i\) 个服务成功提交了自己的本地事务,比如机票真正出票成功。
    TiT_i
  2. 发布事件\(E_i\) 是 \(T_i\) 完成后向外广播的领域事件,比如“机票已出,航班号 XXX”。
    EiE_i
  3. 事件触发链箭头表示订阅了 \(E_i\) 的 \(T_{i+1}\) 被事件触发而执行,整条流程由事件串成接力链。
    Ti→EiTi+1T_i\xrightarrow{E_i}T_{i+1}

5. 对比与选型

跟团游和自由行各有拥趸:跟团省心但行程死板,自由行灵活但全靠自觉。选哪种,取决于你的团队(服务)和路线(流程)的脾气。

对比可以从三个维度看:调用关系复杂度、故障处理方式、流程可见性。编排式有明确的“总导游”,协同式只有模糊的“接力链”。调用链路上,编排式每个服务只跟协调器通信,共 n 条链路;协同式最坏情况下服务间互相引用,链路数可达 \(O(n^2)\)。故障处理上,编排式的补偿逻辑集中在协调器,统一逆序触发;协同式的补偿靠事件往回传,各服务自行实现,状态容易分叉。

选型建议:流程经常变化、涉及团队多、需要全局审计的,选编排式;流程简单线性、团队自治意愿强、想避免单点故障的,选协同式。三五好友自由行毫无压力,上百人的研学团还玩接力传单必然乱套——必须出个总导游。

I编排=O(n),I协同=O(n2)\displaystyle I_{\text{编排}} = O(n), \qquad I_{\text{协同}} = O(n^2)
链路复杂度从“线性”到“平方”的差距,会随着服务数量增长被急剧放大。
  1. 编排式链路\(O(n)\) 读作“线性增长”,n 个服务只需 n 条“服务→协调器”连接,关系一目了然。
    I编排=O(n)I_{\text{编排}}=O(n)
  2. 协同式链路\(O(n^2)\) 说明最坏情况下服务间互相发订阅,连接数随 n 平方膨胀,关系网越织越乱。
    I协同=O(n2)I_{\text{协同}}=O(n^2)
  3. 规模放大差异当 n 很大时,平方级远大于线性级,协同式的关系网会变得难以维护。
    O(n)≪O(n2)(n≫1)O(n) \ll O(n^2) \quad (n \gg 1)

6. 落地实践

不管跟团还是自由行,退订都必须干净利落,否则钱会打水漂。落地 Saga,最见功力的其实是“后手”——补偿、重试和状态恢复。

总结一线实践有四个关键词。第一,补偿要业务化:补偿不是数据库回滚,而是业务反向操作(退票、退款、释放库存)。第二,重试要幂等:补偿和正向操作都要设计成幂等,重复执行 n 次结果一致,否则重试一次就把用户的钱退两次。第三,状态要持久化:协调器要把流程状态落库,重启后从断点恢复,而不是从头再来。第四,失败要对账兜底:重试要有上限和指数退避,最终靠定时对账任务发现“僵尸流程”并人工介入。重试 k 次的累计成功率会快速逼近 1:

每一张订单、每一次退改,都记在旅行社的小本本上。小本本在,就算导游半路换了人,新导游也能照着重来,绝不让同一个订单被退两遍钱——这就是状态持久化与幂等设计的意义。

Pk=1−(1−p)k,f(f(x))=f(x)\displaystyle P_k = 1 - (1 - p)^k, \qquad f(f(x)) = f(x)
左边告诉你“多试几次总行”,右边告诉你“试的时候不能乱来”——幂等是安全重试的前提。
  1. 单次成功率\(p\) 表示一次补偿操作成功完成的概率,例如一次退票调用的成功率。
    pp
  2. 连续失败概率\((1-p)^k\) 表示连续 k 次都失败的可能性,k 越大这个值越小。
    (1−p)k(1-p)^k
  3. 累计成功率\(P_k = 1 - (1-p)^k\) 是重试最多 k 次后至少成功一次的概率,随 k 增大趋近 1。
    Pk=1−(1−p)kP_k=1-(1-p)^k
  4. 幂等性质\(f(f(x)) = f(x)\) 表示同一操作执行两次与执行一次效果相同,这是重试不会造成双倍扣款的前提。
    f(f(x))=f(x)f(f(x))=f(x)

AI 应用场景

电商下单全链路编排

阶段:跨服务业务编排

解决的问题:传统下单要同时扣减库存、创建订单、核销优惠券,这三步分属不同服务,任何一个失败都会造成超卖或脏数据;用编排式 Saga 协调器统一调度,任一环节失败自动逆序补偿。

具体案例:大促期间库存服务超时,协调器收到失败事件后,依次触发“释放优惠券、取消订单”补偿,用户侧最终看到“订单失败已自动退款”,全程无需人工介入。

旅游平台一站式打包预订

阶段:跨服务状态管理

解决的问题:用户一次预订“机票+酒店+门票”套餐,涉及多个外部供应商对接,门票等上游随时可能失败;协同式 Saga 让各服务订阅“订单创建”事件自主处理,失败通过事件链反向取消。

具体案例:用户下单后订单服务发布事件,酒店与门票服务各自订阅完成预订;门票服务因景区关闭取消并发布“取消”事件,酒店服务收到后退订,用户收到全额退款通知。

资金转账与多方记账

阶段:事件驱动集成与最终一致性保障

解决的问题:转账涉及扣款方账户、收款方账户、流水记账三个服务,无法用强一致锁库;用协同式 Saga 以事件串联,靠消息队列持久化保证事件不丢。

具体案例:扣款服务更新余额后发布“扣款成功”事件,记账服务消费后写流水;若记账服务消费失败,通过有限重试和定时对账任务兜底,确保账实相符。

Python 演示

python64 行
# -*- coding: utf-8 -*-"""编排式 Saga 模拟器:总导游逐站安排,失败则反向补偿"""  class SagaCoordinator:    """中央协调器:按序执行正向事务,失败时逆序触发补偿"""     def __init__(self):        self.executed = []     def execute(self, saga):        for step in saga:            try:                step.forward()                self.executed.append(step)            except Exception as e:                print("[失败]" + step.name + ": " + str(e))                print("开始反向补偿:")                while self.executed:                    self.executed.pop().compensate()                print("最终状态: 全部撤销, 行程取消")                return False        print("最终状态: 全部成功, 旅行成行")        return True  class Step:    """一个 Saga 步骤: 正向事务 + 补偿操作"""     def __init__(self, name, forward, compensate):        self.name = name        self._forward = forward        self.compensate = compensate     def forward(self):        print("[执行]" + self.name)        self._forward()  def book_flight():    print("  航班出票成功")  def book_hotel():    print("  酒店确认成功")  def book_sight():    raise RuntimeError("景区当日闭园, 门票预订失败")  def book_restaurant():    print("  餐厅订位成功")  SAGA = [    Step("订机票", book_flight, lambda: print("  已退机票, 票款原路退回")),    Step("订酒店", book_hotel, lambda: print("  已退酒店, 房费原路退回")),    Step("订门票", book_sight, lambda: print("  本次无需补偿(未成功)")),    Step("订餐厅", book_restaurant, lambda: print("  已退餐厅, 订位取消")),] if __name__ == "__main__":    SagaCoordinator().execute(SAGA)
目的:约 50 行实现一个编排式 Saga 模拟器,演示“订机票→订酒店→订门票→订餐厅”旅程中,门票失败后自动反向补偿的逻辑。
  1. class SagaCoordinator:对应编排式里的“总导游”,持有已执行步骤清单
  2. self.executed = []记录已成功的正向步骤,出问题才知道该退谁
  3. step.forward()逐一执行正向本地事务
  4. self.executed.append(step)每成功一步就记一笔账,对应状态机前进
  5. while self.executed:失败时循环弹出已成功步骤
  6. self.executed.pop().compensate()“后进先出”逐项撤销,正好对应退改政策的逆序执行
  7. class Step:把“正向事务 + 补偿操作”打包成一对,即公式里的 \((T_i, C_i)\)
  8. if __name__ == "__main__":只有直接运行脚本时才执行演示,防止被导入时误触发

常见误区

误区学完 Saga 觉得它和数据库事务一样,要么全成功要么全失败,任何时刻都看不到中间状态。机票和酒店应该像被一根线拴着,一荣俱荣一损俱损。

正解Saga 是最终一致性方案,中间状态对外可见——机票可以已出票、酒店还未确认。它的保证是“终态确定”:要么全部正向成功,要么全部补偿完成。就像旅行可以先出机票再慢慢订酒店,只要最终行程确定或全部退款到账即可。

为何常见:人们对 ACID 事务“原子提交”的直觉根深蒂固,容易把 Saga 的成功/补偿误当成同时发生的原子操作,忽略了它的精髓是“最终收敛”。

误区补偿操作就是调用 ROLLBACK,把数据库恢复到操作前的状态,删掉那条订房记录就行。

正解补偿是业务级的反向操作,不是数据库回滚。机票扣款已发生并可能已出票,“退票并退款”是一次全新的业务交易,要调用航司的退款接口,而不是直接删库里的订单行。酒店取消也要走退房费流程,账目上要留下清晰流水。

为何常见:“补偿”这个词容易让人联想到数据库 undo 日志,忽略了分布式环境下每个服务的数据已经独立落库,只能用业务动作去对冲,不能物理撤销。

误区协同式不用写协调器,每个服务发个事件就行,代码量明显更少,所以怎么算都比编排式简单。

正解开发初期协同式确实少写一个协调器,但流程是隐式的,散落在每个服务的订阅逻辑里。排障时要逐个服务翻日志才能拼出全貌,测试也要构造完整事件链。编排式代码虽多,但流程在协调器里一目了然,长期维护成本反而低。

为何常见:只看到“少写一个协调器”的表面收益,忽略了可观测性、排障和测试这些隐性成本,属于“省了开头的钱,欠下后期的债”。

误区消息发到队列里就万事大吉,下游服务总会收到并处理,事件不会丢也不会乱。

正解事件可能丢失、重复、乱序,下游消费也可能有 bug。协同式 Saga 必须配套事件持久化、消费幂等、重试与定时对账。接力棒掉在地上,必须有人能捡起来重新传递,否则整条流程会永远卡死。

为何常见:把消息队列默认成“绝对可靠”的送达管道,忽略了分布式环境下的消息语义(至少一次/恰好一次)问题,这是协同式事故的高发区。

误区补偿失败就一遍遍重试,多试几次总能成功,反正调接口又不用花钱。

正解无限重试会浪费资源、放大流量,还可能带来副作用。正确做法是:有限次重试 + 指数退避 + 人工介入/对账兜底;且重试必须幂等,否则重复退票会把用户的钱退两次。旅行中的“改签失败”也不会无限尝试,而是转到人工柜台处理。

为何常见:直觉上“多试几次总能行”没错,但没意识到重试会重复执行业务动作,忘了给操作加上幂等锁。

面试题

Q1. Saga 模式解决的核心问题是什么?

单选题 · easy

  • A.提高微服务查询性能
  • B.跨服务的最终一致性← 正确答案
  • C.跨服务的强一致性
  • D.简化服务接口设计

答案:B。Saga 是微服务里做跨服务数据一致性的经典模式,核心是“本地事务+补偿”实现最终一致性,而不是强一致(那是 2PC 的目标)。就像跨城旅行:票都能退(补偿),最终要么全成行要么全取消,中途允许部分确定。

Q2. 编排式 Saga 中,由谁负责协调各服务的执行顺序?

单选题 · easy

  • A.各服务自行通过事件通信
  • B.中央协调器统一调度下发← 正确答案
  • C.消息队列自动完成分发
  • D.数据库触发器自动执行

答案:B。编排式 Saga 由中央协调器(总导游)统一调度,各服务被动执行、不感知全局。选项 A 是协同式的特征,C 和 D 与编排式的协调机制无关。

Q3. 下列哪一项是协同式 Saga 的典型特征?

单选题 · mid

  • A.依赖中央状态机驱动流程
  • B.服务间通过事件驱动衔接← 正确答案
  • C.需要额外的协调器节点
  • D.所有服务共享同一数据库

答案:B。协同式没有中央控制器,靠服务间发布/订阅事件推进,像自由行的接力传单。A 和 C 是编排式特征,D 违背了微服务“数据自治”的基本原则。

Q4. 补偿事务 Cᵢ 与正向事务 Tᵢ 的正确关系是?

单选题 · mid

  • A.在前向事务执行之前启动
  • B.撤销前向事务已生效的影响← 正确答案
  • C.与前向事务做完全相同的事
  • D.只在并发冲突发生时才执行

答案:B。Cᵢ 是 Tᵢ 配套的反向业务操作,撤销 Tᵢ 已生效的业务影响,就像退票是出票的“后悔药”。它不是预先执行、不是重复执行,也不是只处理并发冲突。

Q5. 关于 2PC 与 Saga 的对比,下列说法正确的有哪些?

多选题 · mid

  • A.二阶段提交要求参与者全程同步等待← 正确答案
  • B.Saga 通过补偿实现最终一致性← 正确答案
  • C.二阶段提交在分区故障时依然可用
  • D.Saga 允许中间状态短暂不一致← 正确答案

答案:ABD。2PC 第一阶段预提交时参与者要锁资源同步等待(A 对);Saga 用补偿换最终一致性(B 对);2PC 在分区时为保证一致性牺牲可用性,并非“依然可用”(C 错);Saga 过程允许中间状态(D 对)。

Q6. 协同式 Saga 中事件丢失可能导致什么后果?

单选题 · mid

  • A.自动触发下一服务继续推进
  • B.流程停滞且无人知晓原因← 正确答案
  • C.协调器重启即可自动恢复
  • D.数据库自动回滚全部事务

答案:B。协同式靠事件接力,事件丢失后下游毫不知情,流程卡死且难以发现——接力棒掉地上没人捡。A 是正常情况而非丢失后果;协同式没有协调器(C 错);事件丢失也不会自动回滚数据库(D 错)。

Q7. 关于编排式与协同式的适用场景,下列判断正确的有哪些?

多选题 · hard

  • A.业务规则频繁变化适合编排式← 正确答案
  • B.服务团队高度自治适合协同式← 正确答案
  • C.简单直链流程适合编排式
  • D.避免单点故障宜选协同式← 正确答案

答案:ABD。流程频繁变化、多团队协作时编排式集中可控(A 对);团队自治、想避免协调器单点选协同式(B、D 对);简单直链流程通常更适合协同式而非编排式(C 错),少一个协调器反而更轻快。

Q8. 为支持安全重试,补偿操作必须满足的关键性质是什么?

单选题 · hard

  • A.原子性:补偿要么全做要么不做
  • B.幂等性:重复执行结果完全相同← 正确答案
  • C.可逆性:恢复到事务执行前状态
  • D.一致性:补偿结果立即全局可见

答案:B。补偿会被重试反复触发,必须幂等——重复执行 n 次与执行一次结果一致,否则会把用户的钱退两次。可逆/原子/可见都不是补偿的核心要求;补偿是业务反向操作而非状态回滚。

Q9. 关于 Saga 状态管理,下列正确做法有哪些?

多选题 · hard

  • A.只需将状态存在协调器内存
  • B.将流程状态持久化到数据库← 正确答案
  • C.重启后从持久化状态恢复← 正确答案
  • D.状态不落盘以换取更高性能

答案:BC。协调器状态必须持久化,重启后从断点恢复流程(B、C 对)。只放内存(A)一重启就丢,不落盘(D)无法保证可靠恢复——就像行程单必须写在小本本上,不能只靠导游脑子记。

Q10. 一个包含 n 个服务的 Saga,编排式协调器维护的调用关系复杂度通常是什么?

单选题 · extreme

  • A.常数级:永远只需保持一条连接
  • B.线性级:与每个服务各建一条链路← 正确答案
  • C.平方级:服务之间全部互相直连
  • D.对数级:随服务数量对数增长

答案:B。编排式每个服务只与协调器一条链路,共 n 条,复杂度 O(n);协同式最坏情况下服务间互相发布订阅,链路可达 O(n²)。这是两者耦合度差异的量化体现,也是选型的重要依据。