知识卡片

SAGA用正向反向补偿应对无法冻结资源的场景

普通读书笔记卡

内容

[[TCC的Try-Confirm-Cancel如何在分布式事务中保留隔离性]]的Try阶段要求能 自主”冻结”资源,但这个前提并不总是成立——例如用户改用银行U盾/扫码直接 支付而非系统内充值账户时,货款的操作权限归银行所有,系统根本无法要求 银行配合冻结/解冻,TCC的第一步就无法实施。SAGA事务的思路完全不同:把 一个大事务拆成若干可以交错执行的子事务T₁…Tₙ,同时给每个子事务设计一个 补偿动作C₁…Cₙ(子事务和补偿动作都必须幂等,且互相满足交换律——先执行 哪个效果都一样)。如果全部子事务成功,事务顺利结束;一旦某个子事务Tᵢ失败, 有两种恢复策略:正向恢复——不断重试Tᵢ直到成功,适用于”这笔交易必须 成功”的场景(如已经在银行扣了款就必须发货);反向恢复——不断执行已完成 子事务的补偿动作Cᵢ、Cᵢ₋₁…C₁直到回滚成功,适用于货款还能退回的场景 (把已从银行划转来的钱转回用户账户,即使系统无法要求银行撤销原转账,这 个补偿动作依然可行)。相比TCC,SAGA不需要设计”冻结”这种中间状态,补偿 操作实现起来通常更容易,但同样需要SAGA Log记录执行进度以便系统崩溃后 恢复追踪。

参考来源

- 位置:《凤凰架构:构建可靠的大型分布式系统》第3章"事务处理"3.4.4节 "SAGA事务"(源文件:_epub-src对应OEBPS/Text/chapter34.xhtml) - 结论依据:原文用"用户通过银行直连支付、无法冻结货款"的场景说明TCC 的局限,进而介绍SAGA子事务与补偿动作的设计要求(幂等、交换律),以及 正向恢复、反向恢复两种策略各自的适用场景,直接支撑本卡片结论。 - 原始内容:如果用户、商家的账号余额由银行管理的话……通常也就无法完成 冻结款项、解冻、扣减这样的操作……所以TCC中的第一步Try阶段往往无法 施行。我们只能考虑采用另外一种柔性事务方案:SAGA事务。