想象你带着全家五口人周末出游:先在某平台订机票,再在另一个App订酒店,最后还要抢景区门票。每个环节单独看都不难,但它们环环相扣——机票订好了、酒店却没房了,怎么办?老派的办法是:让三个商家同时锁定资源,确认都有货再一起扣款。可一旦中间断网,所有座位和房间都得一直被占着,别人也订不了,全家就在“等待”里干熬。Saga模式给出了另一种思路:不用同时锁定,一项一项来——订完机票订酒店,订完酒店订门票;哪个环节失败了,就把之前订好的逐一退掉,谁也不用干等。这就是分布式事务领域的“旅行团式解决方案”,用拆解替代锁定,用补偿替代回滚,最终让全家依然顺利成行或全身而退。

岗位关联

掌握Saga模式,是微服务架构师处理跨服务数据一致性的核心技能,能帮你在保证系统高可用的前提下优雅解决分布式事务难题。

目录
  1. 可视化演示
  2. Saga概念解析
  3. 编排式Saga
  4. 协同式Saga
  5. 补偿操作设计
  6. 幂等控制策略
  7. 协议对比选型
  8. Seata实践
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

动态演示Saga模式处理分布式事务的核心机制,通过采集/分析/决策/反馈四种模式展示关键概念与交互流程。

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

Saga模式处理分布式事务:Saga Saga模式核心理念与分布式事 编排式与协同式Saga对比 核心机制可视化 Saga模式处理分布式事务整体架构与关键组件

Saga概念解析

全家旅行团的第一课,叫“别再开家庭会议”。过去订机票、酒店、门票,总想全家凑齐了一次性同步搞定——这就是传统分布式事务的“举手表决”思路。Saga模式反其道而行:把一段复杂的全家旅行,拆成“订机票→订酒店→订门票”三个独立小项目,每完成一项就签收一项,谁也不用等谁。这种拆解的智慧,正是Saga解决分布式事务的起点。

从技术角度看,Saga模式把一个跨多个微服务的“大事务”,拆分成一系列有先后顺序的“本地事务”(Local Transaction)。每个本地事务都在各自的微服务内独立提交,立刻释放数据库锁资源。整条链路上的事务按顺序执行,一旦某个本地事务执行失败,Saga就会调用之前已完成事务的补偿操作,让业务状态一步步回到起点。

这里的关键在于“Saga只保证最终一致性,而非强一致性”。传统事务要求任何时刻所有节点状态完全一致,Saga则允许中间过程存在短暂的不一致——比如机票已订而酒店未订——只要最终要么全部成功、要么全部撤销即可。下面是Saga的结构化表达:

TiT_i 表示第 $i$ 个正向本地事务

CiC_i 表示第 $i$ 个补偿事务

∪\cup 表示两者的并集组合

回到旅行团的例子:Saga让“订机票”和“订酒店”变成两个独立签约的小合同,而不是一个必须同时生效的生死契约。就算酒店没订上,退掉机票就能重新出发——全家不会被困在“等待所有家人都同意”的僵局里。这就是Saga的核心哲学:用可拆解的行动替代不可退让的承诺。

Saga={T1,T2,…,Tn}∪{C1,C2,…,Cn}\displaystyle \text{Saga} = \{T_1, T_2, \ldots, T_n\} \cup \{C_1, C_2, \ldots, C_n\}
Saga是正向本地事务与补偿事务的集合,事务之间通过编排或协同方式串联。
  1. Saga整体定义Saga由两组事务共同构成,一组负责前进,一组负责善后。
    Saga={T1,T2,…,Tn}∪{C1,C2,…,Cn}\displaystyle \text{Saga} = \{T_1, T_2, \ldots, T_n\} \cup \{C_1, C_2, \ldots, C_n\}
  2. 正向事务Ti每个T是微服务内的本地事务,例如“订单服务创建订单”。
  3. 补偿事务Ci每个C与对应的T配对,执行反向业务操作,例如“取消订单”。
  4. 并集关系正向与补偿共同构成完整的Saga定义,缺一不可。

编排式Saga

如果说Saga是把旅行拆成了小项目,那“编排式”就是给这个团配了一位全职导游。导游手里攥着一份详细行程单,他的职责是告诉每个家庭成员:“现在你去订机票”“接下来你去订酒店”“最后你去买门票”。所有人只听导游安排,互相之间不需要沟通。这位导游,就是编排式Saga里的中央协调者(Orchestrator)。

在编排式Saga中,Orchestrator是一个独立服务,负责定义并驱动整个事务流程。它通过命令或RPC调用各个参与服务,等待每个服务返回结果后,再决定下一步动作。如果某个服务返回失败,Orchestrator会依据预设的流程,反向调用已成功服务的补偿接口。所有流程状态都集中在协调者内部,因此链路清晰、易于监控和恢复。

编排式Saga的状态流转可以用下面这个公式概括:协调者总是根据“当前状态+最新事件”计算出下一个状态。整个过程像一个有限状态机,每个阶段都由协调者显式推进,而不是让服务之间互相“商量”。

Statek\text{State}_k 表示第 $k$ 步的流程状态

Eventk\text{Event}_k 表示第 $k$ 步收到的服务反馈

Orchestrator(⋅)\text{Orchestrator}(\cdot) 是中央协调者的决策逻辑

Statek+1\text{State}_{k+1} 表示递推得到的下一状态

导游模式的优点是显而易见的:所有决策都集中在一处,团队不会乱。但在技术世界里,这位“导游”也承担了巨大的压力——他必须清楚每一个景点的规则,一旦行程变更,所有调整都压在他一个人身上。这也是编排式Saga的代价:协调者本身成为高可用设计的关键节点。

Statek+1=Orchestrator(Statek,Eventk)\displaystyle \text{State}_{k+1} = \text{Orchestrator}(\text{State}_k, \text{Event}_k)
协调者根据当前状态和收到的事件,计算并转移到下一个状态。
  1. 当前状态State_k表示Saga执行到第k步时的进度,比如“已订机票”。
  2. 输入事件Event_k参与服务返回的结果,如“酒店预订成功”或“支付失败”。
  3. 协调者决策函数Orchestrator是一个决策器,输入上述两者输出新状态。
  4. 状态递推新状态成为下一步的输入,形成可追踪的状态链。

协同式Saga

这次不带导游了。全家自由行,爸爸负责订机票,订完在家庭群里发一条消息:“机票搞定!”妈妈看到消息后去订酒店,订完再发一条:“酒店OK!”儿子看到后去买门票。每个人只关心“上一个事件”和“自己的任务”,谁也不需要盯着别人干活。这种靠消息接力推进的方式,就是协同式Saga(Choreography)。

协同式Saga没有中心协调者,各服务之间通过消息队列或事件总线解耦。每个服务在完成自己的本地事务后,发布一个领域事件;下游服务订阅该事件,如果自己的事务执行失败,则发布一个失败事件,之前已完成事务的服务在收到失败事件后触发各自的补偿操作。整个流程“隐藏”在事件流里,天然地实现了服务间的松耦合。

用公式表达,协同式Saga中下一个事务的触发条件,是上一个事务发出的事件。服务之间不依赖“导游”,而是依赖“消息”这封接力信:

Eventi\text{Event}_i 表示服务 $i$ 发出的事务事件

f(⋅)f(\cdot) 表示服务的订阅响应逻辑

Ti+1T_{i+1} 表示下一个被触发的本地事务

自由行的好处是每个人都很轻松,谁也不用当总指挥;但坏处是一旦环节变多,链条会变得难以追踪——你想知道全家现在走到哪一步了,得翻遍所有聊天记录。协同式Saga也是如此:它极致灵活、去中心化、扩展性极强,但流程的可观测性较弱,适合参与方少、链路固定的场景。选择导游还是自由行,取决于你的团队规模和可管控性需求。

Ti+1=f(Eventi)\displaystyle T_{i+1} = f(\text{Event}_i)
下一个正向事务由上一个事务发布的事件触发。
  1. 上游事件Event_i第i个服务完成或失败后发布的领域事件。
  2. 触发函数每个服务内部定义了事件处理逻辑,收到事件后开始执行自己的事务。
  3. 事务接力第i+1个事务成为新的消息发布者,继续传递接力棒。

补偿操作设计

旅行中最怕什么?怕酒店超卖。到了前台才发现没房,这时候该怎么办?全家老小在酒店大堂干等着,肯定不行——得赶紧启动“善后模式”:取消没住的酒店,退掉可能订好的接送机,如果机票也能退就一起退掉,让全家毫发无损地回到原计划。这一连串的“退订操作”,就是Saga模式中的补偿事务(Compensating Transaction)。

设计补偿操作时,最重要的一条原则是:补偿不是数据库回滚,而是业务层面的反向操作。数据库回滚是把磁盘上的记录“抹掉”,仿佛没发生过;而补偿是执行一个新的业务动作,比如“取消订单”“退款”“释放库存”。这意味着你需要在每个参与服务中,额外开发一套可调用的补偿接口——就像每个景点都要有一个“退票窗口”。

补偿的执行顺序必须与正向顺序严格相反。比如正向是“订机票→订酒店→订门票”,如果订门票失败,补偿顺序就是“退门票(未执行不需要)→退酒店→退机票”,写成序列就是:

Ci−1C_{i-1} 表示第 $i-1$ 个事务的补偿操作

Ci−2,…,C1C_{i-2}, \ldots, C_1 表示继续向前回溯的补偿序列

{C1,…,Ci−1}\{C_1, \ldots, C_{i-1}\} 组成完整补偿集合

补偿设计得好不好,决定了Saga在真实世界能不能落地。就像酒店退订,如果对方要求你提供“入住人身份证原件”才能退款,那这个补偿流程就没法自动化,业务上就卡壳了。设计补偿时必须站在业务角度思考:这个反操作在当前业务规则下是否可行、是否需要人工介入、是否可能失败——这些都是在画Saga流程图之前就要想清楚的。

Compensation={Ci−1,Ci−2,…,C1}\displaystyle \text{Compensation} = \{C_{i-1}, C_{i-2}, \ldots, C_1\}
当第i个正向事务失败时,对前i-1个已完成事务按逆序执行补偿。
  1. 失败锚点Ci-1补偿序列从失败节点的前一个事务开始回退。
  2. 逆序原则补偿严格按正向执行的相反顺序进行,保证业务依赖链条不被破坏。
  3. 完成的边界只有已经成功提交的事务才需要补偿。

幂等控制策略

旅行团到了酒店前台。退房时,工作人员说押金已退还到你的账户,但你没收到短信。你追问了一句,工作人员又操作了一次退款——结果到账了两笔押金。谁都没做错,但钱多给了。这时候,前台系统最需要什么?需要“幂等”:同一个退款请求,无论执行多少次,结果都只能有一个。

幂等(Idempotency)是Saga中补偿操作和重试机制的安全底座。Saga执行过程中,网络超时、机器宕机都可能导致同一个请求被发送多次;补偿操作也可能因为异常被重复触发。如果接口不幂等,重复的退款、重复的扣库存、重复的取消订单就会污染数据。解决方案通常是:为每个请求分配一个唯一业务键(如订单号、事务ID),服务端记录已处理过的键并直接返回原结果。

用数学语言描述,一个操作f是幂等的,意味着对同一个输入x执行两次和执行一次结果完全相同。这正是重试机制敢放心大胆地“再试一次”的前提。在Saga里,无论是正向事务还是补偿事务,接口设计都应该遵守这个性质:

f(⋅)f(\cdot) 表示任意一个业务操作

xx 表示请求的唯一标识

f(f(x))f(f(x)) 表示操作被连续执行两次

f(f(x))=f(x)f(f(x)) = f(x) 说明执行多次等价于执行一次

幂等性就像给每个业务动作装上一道“闸门”:同一个请求进来,第二次直接放行不处理。有了这道闸门,Saga中的补偿操作才敢放心重试、超时恢复时也敢重放消息。记住:没有幂等机制的Saga,就像一个忘记确认退押金次数的酒店前台——不是会不会出错,而是迟早会出错。

f(f(x))=f(x)\displaystyle f(f(x)) = f(x)
同一个操作执行多次与执行一次效果相同,这就是幂等的数学定义。
  1. 操作函数f代表某个业务接口,例如“退款接口”。
  2. 输入x代表请求参数,如唯一的退款单号。
  3. 执行两次操作重复执行时,第二次会因唯一键冲突而返回第一次的结果。
  4. 幂等条件两次执行的结果与执行一次完全相同。

协议对比选型

现在你已经见识了三套旅行方案。老派方案“开家庭大会”:全家围坐一圈,必须每个人都拿到确认单才允许行动,有任何一个人犹豫就全部搁置——这是两阶段提交(2PC)。进阶方案“先交定金占位”:每个环节先预留名额,等全都确认后统一转正,有谁掉链子就释放所有预留——这是TCC。今天的主角Saga则是“逐项签约、随时可退”:一项项办、一项项退,绝不长时间占着资源不放。

三套方案各有代价。2PC能提供最强的实时一致性,但需要占用资源直到事务结束,网络分区或节点故障时会长时间阻塞。TCC通过预留资源实现了业务层面的强隔离,但需要业务方实现Try/Confirm/Cancel三个方法,开发成本高、侵入性强。Saga则把长事务分成短事务,每个短事务立即提交并释放资源,用补偿换取可用性,代价是中间状态对外可见、隔离性偏弱。三者的关系可以用一个简明的谱系来表达:

2PC≥TCC≥Saga\text{2PC} \geq \text{TCC} \geq \text{Saga} 表示一致性强度递减

2PC≤TCC≤Saga\text{2PC} \leq \text{TCC} \leq \text{Saga} 表示可用性递增

一致性↑⇒可用性↓\text{一致性} \uparrow \Rightarrow \text{可用性} \downarrow 强一致必然牺牲可用性

所以怎么选?如果业务像银行转账一样需要实时强一致、事务链路短,2PC依然是合适的;如果业务链路中等、愿意投入开发实现Try/Confirm/Cancel,TCC能带来更好的隔离性;如果业务链路长、服务多、追求高吞吐和弹性,比如电商下单要经过订单→支付→库存→物流,Saga才是最优解。选型不是攀比谁更先进,而是看谁最能匹配你的业务代价承受力。

一致性强度: 2PC≥TCC≥Saga;可用性: 2PC≤TCC≤Saga\displaystyle \text{一致性强度}:\ 2\text{PC} \geq \text{TCC} \geq \text{Saga};\quad \text{可用性}:\ 2\text{PC} \leq \text{TCC} \leq \text{Saga}
一致性越强的方案通常可用性越低,Saga选择用弱一致性换取高可用。
  1. 一致性排序2PC在同一时刻对所有节点可见,TCC通过占位基本保证,Saga只保证最终。
  2. 可用性排序Saga事务短、不锁资源、不怕长阻塞,所以可用性最高。
  3. 工程取舍两项排序方向相反,说明不存在“全能方案”,只有匹配场景的方案。

Seata实践

讲了这么多理论,有没有一个工具能把“导游”“补偿”“幂等”三件事都管起来?开源分布式事务框架Seata给出了回答:它内置了Saga状态机引擎,相当于一台“旅行规划App”。你只要在页面上画出行程步骤——第一步做什么、失败了去哪退订——引擎就会自动按图执行,并帮你管理补偿链路的调用。

Seata的Saga实现特别适合编排式场景。开发者通过JSON或Groovy定义状态机,每个状态是一个服务调用,可以配置成功下一个状态、失败的下一个状态以及补偿动作。状态机执行到失败节点时会自动回溯,用户不需要手写“谁来谁退”的流程代码。Seata服务端还负责事务日志、状态的持久化和恢复,配合控制台可以查看每一步的执行情况。

Seata状态机的核心机制可以用状态转移公式理解:每个状态的去向由当前状态和反馈结果共同决定,引擎根据这个转移函数驱动流程前进或退出。这正是前面编排式Saga的“导游”逻辑的工程化实现:

ScurrentS_{\text{current}} 表示状态机当前停留的节点

Result\text{Result} 表示服务执行结果

δ(⋅)\delta(\cdot) 表示状态转移规则

SnextS_{\text{next}} 表示根据规则计算出的目标状态

有了Seata,Saga的落地门槛被大幅降低——你不用从零搭建协调者,也不用自己设计补偿调度。就像旅行App把“退票窗口”搬到了手机里,一切流程可视化、可追踪。当然,工具只是助手,真正的业务补偿逻辑和幂等设计仍然需要每个微服务自己实现。工具帮你把流程串起来,但让流程每一步都走得稳,靠的还是我们今天讲的所有基本功。

Snext=δ(Scurrent,Result)\displaystyle S_{\text{next}} = \delta(S_{\text{current}}, \text{Result})
状态机引擎根据当前状态与执行结果,决定下一个状态是前进还是补偿。
  1. 当前状态S_current例如“订单创建完成”或“支付处理中”。
  2. 执行结果Result服务调用的返回值,成功或失败。
  3. 转移函数δ状态机的核心表,定义每种“状态+结果”组合的跳转方向。
  4. 下一状态S_next可能是下一个正向节点,也可能是补偿节点或结束节点。

AI 应用场景

电商平台订单全链路

阶段:跨服务数据一致性保障

解决的问题:用户在电商App下单后,系统要依次创建订单、扣减库存、扣除优惠券、生成物流单。传统做法要么用数据库强事务锁死所有表(性能差),要么各服务独立提交(数据不一致)。Saga将整个下单链路编排成一系列本地事务,任何一步库存不足,就自动重新释放优惠券并将订单作废,保证全链路最终一致。

具体案例:双十一大促高峰期,用户在购物车提交了5件商品。订单服务创建订单成功,支付服务扣款成功,库存服务发现其中一件已售罄。此时Saga协调者依次触发“释放支付扣款”“撤销订单”两个补偿操作,用户看到“因库存不足,订单已取消并退款”的提示,整个流程在2秒内完成回滚。

跨行转账聚合支付

阶段:分布式事务恢复与幂等控制

解决的问题:聚合支付平台处理“用户A银行账户→平台中间账户→商家B银行账户”的两段式转账,涉及两个不同银行系统的协作,不可能用数据库本地事务。Saga先执行“扣减A行余额”,再执行“增加B行余额”;若B行入账失败,则执行补偿操作“退回A行余额”,同时依赖幂等控制避免重复退钱。

具体案例:某平台用户在6月18日凌晨发起一笔5万元跨行转账,B行系统因升级短暂不可用,入账失败。Saga状态机自动触发补偿,A行余额在3秒内原路退回;用户次日收到“转账未成功,资金已退回”的短信通知,整个回退过程无需人工介入。

Python 演示

python50 行
class Service:    def __init__(self, name):        self.name = name     def execute(self, tx_id):        print("[%s] 执行正向事务 %s" % (self.name, tx_id))        return True     def compensate(self, tx_id):        print("[%s] 执行补偿操作 %s" % (self.name, tx_id))  class StockService(Service):    def execute(self, tx_id):        print("[%s] 执行正向事务 %s" % (self.name, tx_id))        # 模拟库存不足导致事务失败        if tx_id == "T002":            print("[%s] 库存不足, 事务失败!" % self.name)            return False        return True  class SagaCoordinator:    def __init__(self, services):        self.services = services        self.done = []     def run(self, tx_id):        print("=== Saga 编排开始: %s ===" % tx_id)        for svc in self.services:            if svc.execute(tx_id):                self.done.append(svc)            else:                print("--- %s 失败, 开始逆向补偿 ---" % svc.name)                for s in reversed(self.done):                    s.compensate(tx_id)                return False        print("所有事务执行成功")        return True  if __name__ == "__main__":    order = Service("订单服务")    pay = Service("支付服务")    stock = StockService("库存服务")    saga = SagaCoordinator([order, pay, stock])    print("\n--- 正常流程演示 ---")    saga.run("T001")    print("\n--- 失败补偿演示 ---")    saga.run("T002")
目的:模拟编排式Saga协调器,按顺序执行订单→支付→库存三个本地事务,库存不足时自动逆向触发补偿。
  1. class SagaCoordinator:定义中央协调者,负责按顺序驱动各服务事务。
  2. self.done = []记录已成功执行的服务名单,作为补偿的依据。
  3. if svc.execute(tx_id):依次调用每个服务的正向事务,检查是否成功。
  4. for s in reversed(self.done):失败时对已完成服务按逆序调用补偿操作。
  5. class StockService(Service):继承并重写执行逻辑,模拟库存不足的业务失败。

常见误区

误区用Saga模式后就可以高枕无忧,任何时刻读到的数据都是最新最准的,跟单机数据库事务一样可靠。

正解Saga是最终一致性方案。正向事务执行期间,各服务之间会有一段“账对不上”的窗口期。就像旅行中机票已买而酒店未定时,全家的行程还在变化中。它牺牲了强一致,换来了高可用和低资源占用。如果业务需要实时一致性(如余额查询),Saga并不合适。

为何常见:非专业人士容易把“分布式事务”笼统理解为“保证一致”,忽略了ACID与BASE之间的本质差异。

误区Saga执行失败时,系统会自动把数据库里的数据“还原”成事务开始之前的样子,像什么都没发生过一样。

正解补偿是业务层面的反向操作,不是物理回滚。比如“支付服务扣款成功”,补偿不是删掉那条扣款记录,而是新增一条“退款”记录。就像酒店退订,不会把你的入住记录凭空抹去,而是生成一条“取消预订”的新记录。设计补偿时必须从业务规则出发,确保反向操作在业务上说得通。

为何常见:受数据库事务的"UNDO"概念影响,想当然地认为所有回滚都该由底层机制自动完成。

误区只要给每个请求加上一个唯一ID,接口就自动幂等了,重试和补偿随便发。

正解唯一键只是幂等的前提条件之一。服务端还必须做“已处理记录”的落库校验、状态机流转校验、以及并发场景下的唯一索引兜底。如果服务收到重复请求但还没来得及写入记录就宕机了,重试依然可能重复处理。幂等是一个完整的防御体系,不是一行"SET UNIQUE"就能解决的。

为何常见:把数据库唯一约束的机制等同于完整的幂等方案,忽略了分布式环境下“检查-执行”之间的时间窗问题。

误区既然编排式有中央协调者,流程清晰可控,那所有Saga都应该用编排式实现,协同式过时了。

正解编排式和协同式各有适用边界。编排式把流程集中到一个协调者,协调者可能成为性能瓶颈和单点故障;协同式完全去中心化,新增服务只要订阅事件就能接入,扩展性更强。就像大旅行团需要导游带队,但三五好友自由行时导游反而碍事。选型要结合团队规模、链路长度、可观测性需求综合判断。

为何常见:拿“有无中心控制”这一维度简单判断优劣,忽略了高可用、可扩展、可维护等多个工程维度的权衡。

面试题

Q1. Saga模式将长事务拆分成多个什么来执行?

单选题 · easy

  • A.全局锁任务
  • B.本地独立事务← 正确答案
  • C.分布式表备份
  • D.消息队列任务

答案:B。Saga的核心思想是把跨服务的全局事务拆成一系列微服务内的本地事务,每个本地事务独立提交并释放资源。全局锁任务、表备份、消息队列都不是Saga拆分的基本单位。

Q2. Saga模式最终实现的是哪种一致性?

单选题 · easy

  • A.强一致性
  • B.最终一致性← 正确答案
  • C.实时一致性
  • D.读写一致性

答案:B。Saga允许中间状态短暂不一致,只要最终所有事务成功或全部补偿即可,因此它保证的是最终一致性。强一致性需要2PC或TCC这类资源预留型方案。

Q3. 编排式Saga的典型特征有哪些?

多选题 · mid

  • A.中央协调者统一调度← 正确答案
  • B.服务间事件驱动交互
  • C.流程定义集中管理← 正确答案
  • D.无需额外协调组件

答案:AC。编排式Saga有一个独立的中央协调者,集中定义流程并调度各服务,因此A和C正确。事件驱动交互和无需协调组件是协同式Saga的特征。

Q4. 在Saga补偿流程中,补偿事务的执行顺序是?

单选题 · easy

  • A.正向顺序
  • B.逆序执行← 正确答案
  • C.随机顺序
  • D.并行执行

答案:B。补偿必须严格按正向事务的逆序执行,就像退订酒店要先于退订机票一样。因为后序事务往往依赖前序事务的结果,只有逆序回退才能保证业务链路不被破坏。

Q5. 实现分布式事务接口幂等性的常用策略有?

多选题 · mid

  • A.唯一业务键约束← 正确答案
  • B.状态机流转校验← 正确答案
  • C.反范式冗余存储
  • D.全链路日志追踪

答案:AB。唯一业务键让重复请求命中同一记录,状态机校验确保只有合法状态的请求才会被处理,这两者是幂等的主要手段。冗余存储和日志追踪不直接提供幂等保障。

Q6. 与两阶段提交相比,Saga模式的显著优势是?

单选题 · mid

  • A.更好的全局锁性能
  • B.更高的系统可用性← 正确答案
  • C.更简单的回滚逻辑
  • D.更强的隔离性保证

答案:B。Saga每个本地事务立即提交并释放资源,不长时间占用锁,因此在长事务场景下可用性显著高于2PC。2PC才是真正意义上的全局锁。Saga的回滚逻辑和隔离性通常比2PC更复杂或更弱。

Q7. Seata Saga状态机中,Compensate节点的作用是什么?

单选题 · hard

  • A.提交所有正向事务
  • B.执行逆向补偿逻辑← 正确答案
  • C.同步阻塞等待结果
  • D.分配分布式锁资源

答案:B。Compensate节点是状态机中专门执行补偿操作的节点。当某一步正向服务调用失败时,状态机自动调用之前成功步骤的Compensate节点完成补偿。它负责逆向业务逻辑,而非提交事务或分配锁资源。

Q8. 关于Saga与TCC的区别,下列说法正确的是?

多选题 · hard

  • A.TCC需业务方实现三方法← 正确答案
  • B.Saga补偿依赖数据库回滚
  • C.TCC通常比Saga隔离性更强← 正确答案
  • D.Saga实现一定比TCC更简单

答案:AC。TCC要求业务方实现Try/Confirm/Cancel三个方法,A正确。TCC通过预留资源保证更强隔离性,C正确。Saga的补偿不是数据库回滚而是业务反向操作,B错误。Saga不一定比TCC简单,两者复杂点不同,D中的“一定”过于绝对。

Q9. Saga模式中的“空补偿”问题是指什么?

单选题 · extreme

  • A.补偿逻辑未编写就执行
  • B.正向未完成却执行补偿操作← 正确答案
  • C.补偿操作执行产生新错误
  • D.多个补偿事务触发并发冲突

答案:B。空补偿指正向事务尚未执行完毕或根本没执行,却因为消息乱序等原因收到了补偿请求。此时补偿操作面对的是一个“空”的业务状态。工程上需要在补偿逻辑内校验存在性,必要时结合悬挂检测综合处理。

Q10. 下列哪些场景适合使用Saga模式?

多选题 · mid

  • A.跨服务订单创建流程← 正确答案
  • B.银行账户实时余额扣减
  • C.库存扣减与物流系统协同← 正确答案
  • D.单机数据库事务操作

答案:AC。跨服务订单创建流程和库存物流协同是典型的链路长、服务多、允许短暂不一致的业务,适合Saga。银行实时余额扣减需要强一致,更适合TCC或2PC;单机数据库事务直接用本地事务即可,不需要分布式方案。