分布式事务


2PC、TCC、SAGA、本地消息表的原理和优缺点分别是什么?在实际项目中如何选择合适的分布式事务方案?

特性 2PC TCC SAGA 本地消息表
一致性 强一致性(ACID) 强一致性(近似 ACID) 最终一致性 最终一致性
业务侵入性 低(依赖数据库) 高(需实现 3 个方法) 中(需实现补偿事务) 低(需加消息表)
性能 低(同步阻塞) 高(无阻塞) 高(无阻塞) 高(异步消息)
实现复杂度 高(处理幂等 / 空回滚) 中(协调式易管理)
适用事务长度 短事务 短事务 长事务 中短事务
核心问题 同步阻塞、单点故障 业务侵入、实现复杂 补偿逻辑、最终一致 消息延迟、幂等性

SAGA

将分布式事务拆分为一系列本地事务的有序执行链,每个本地事务都有对应的补偿事务:

正向执行

按顺序执行每个本地事务 T1, T2, …, Tn。
如果所有本地事务都执行成功,事务提交。

反向补偿

如果某个本地事务 Ti 执行失败,按逆序执行补偿事务 Ci-1, Ci-2, …, C1。
补偿事务的作用是撤销对应正向本地事务的执行结果,恢复到事务执行前的状态。

TCC(Try-Confirm-Cancel,补偿事务)

upload successful

TCC 是一种业务侵入式的分布式事务方案,将每个业务操作拆分为三个独立的方法,由业务代码实现:

1.Try 阶段

尝试执行业务操作,预留资源(如冻结资金、锁定库存),保证操作的幂等性。

此阶段只做资源检查和预留,不执行最终业务逻辑。

2.Confirm 阶段

确认执行业务操作,使用预留的资源完成最终逻辑。

只有当所有参与者的 Try 阶段都成功时,才会执行 Confirm 阶段。

3.Cancel 阶段

取消执行业务操作,释放预留的资源。

如果任何一个参与者的 Try 阶段失败,会执行所有参与者的 Cancel 阶段。

幂等、空回滚、悬挂?

幂等性就是无论接口调用多少次,返回的结果应该具有一致性。

空回滚(try没执行就cancel):当某分支事务的try阶段阻塞时,可能导致全局事务超时而触发二阶段的cancel操作。在未执行try操作时先执行了cancel操作,这时cancel不能做回滚,就是空回滚。

业务悬挂(cancel之后try):对于已经空回滚的业务,如果以后继续执行try,就永远不可能confirm或cancel

  • 资金业务的具体例子:

为了实现空回滚、防止业务悬挂,记录冻结金额的同时,记录当前事务id和执行状态

1
2
3
4
5
6
7
CREATE TABLE `account_freeze_tbl` (
`xid` varchar(128) NOT NULL COMMENT '事务id',
`user_id` varchar(255) DEFAULT NULL COMMENT '用户id',
`freeze_money` int(11) unsigned DEFAULT '0' COMMENT '冻结金额',
`state` int(1) DEFAULT NULL COMMENT '事务状态,0:try,1:confirm,2:cancel',
PRIMARY KEY (`xid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

1.Try业务

记录冻结金额和事务状态0到account_freeze表

扣减account表可用金额

2.Confirm业务

根据xid删除account_freeze表的冻结记录(因为如果一个事务confirm那么记录就没有意义了)

3.Cancel业务

修改account_freeze表,冻结金额为0,state为2

修改account表,恢复可用金额

  • 如何判断是否空回滚:

cancel业务中,根据xid查询account_freeze,如果为null则说明try还没做,需要空回滚

  • 如何避免业务悬挂:

try业务中,根据xid查询account_freeze ,如果存在金额=0/state=2则证明Cancel已经执行,拒绝执行try业务

TCC vs 2PC

TCC只需要处理业务异常情况,异常处理相对简单。 2PC适用于对事务一致性要求较高的场景,例如银行转账等,需要保证数据致性和完整性。 而TCC适用于对事务一致性要求不那么高的场景,例如电商库存扣减等,需要保证数据最终一致性即可。

本地消息表

写本地消息+状态,然后链式流转。

文章目录
  1. 1. SAGA
  2. 2. TCC(Try-Confirm-Cancel,补偿事务)
  3. 3. TCC vs 2PC
  4. 4. 本地消息表
| 本站总访问量次 ,本文总阅读量