两阶段提交(XA)
XA 规范主要定义了全局事务管理器(TM)和局部资源管理器(RM)之间的接口。本地的数据库如 mysql 在 XA 中扮演的是 RM 角色。
XA一共分为两阶段:
- 第一阶段(prepare):即所有的参与者RM准备执行事务并锁住需要的资源。参与者ready时,向TM报告已准备就绪。对于数据库来说,准备阶段指在重做日志(redo log)中记录所有操作的内容(与真正提交的区别在于没有最后一句 commit)。
- 第二阶段 (commit/rollback):当事务管理者(TM)确认所有参与者(RM)都 ready 后,向所有参与者发送 commit 命令。 数据库只在第二阶段执行 commit 命令,通常能快速完成。
- 如果有任何一个参与者 prepare 失败,那么TM会通知所有完成 prepare 的参与者进行回滚。
目前主流的数据库基本都支持XA事务,包括 mysql、oracle、sqlserver、postgre,数据库的 TM 与 RM 通常都是由数据库自己扮演,TM 一般来说是在 RM 中选举产生。
特点:
- 简单易理解,开发较容易
- 对资源进行了长时间的锁定,并发度低
- 如果 TM 宕机,所有节点都受影响
SAGA
SAGA 的核心思想是将长事务拆分为多个本地短事务,由Saga事务协调器协调。如果正常结束那就正常完成,如果某个步骤失败,则根据相反顺序一次调用补偿操作。
Saga 一旦到了 Cancel 阶段,那么 Cancel 在业务逻辑上是不允许失败了。如果因为网络或者其他临时故障,导致没有返回成功,那么 TM 会不断重试,直到 Cancel 返回成功。
特点:
- 并发度高,不用像 XA 事务那样长期锁定资源
- 需要定义正常操作以及补偿操作,开发量比 XA 大
- 一致性较弱,对于转账,可能发生A用户已扣款,最后转账又失败的情况
TCC(Try-Confirm-Cancel)
TCC 分为3个阶段:
- Try 阶段:尝试执行,完成所有业务检查(一致性),预留必须业务资源(准隔离性)
- Confirm 阶段:确认执行,真正执行业务,不作任何业务检查,只使用 Try 阶段预留的业务资源,Confirm 操作要求具备幂等设计,Confirm 失败后需要进行重试。
- Cancel 阶段:取消执行,释放 Try 阶段预留的业务资源。Cancel 阶段的异常和 Confirm 阶段异常处理方案基本上一致,要求满足幂等设计。
上面的转账作为例子,通常会在Try里面冻结金额,但不扣款,Confirm里面扣款,Cancel里面解冻金额。
TCC 的 Confirm/Cancel 阶段在业务逻辑上是不允许返回失败的,如果因为网络或者其他临时故障,导致不能返回成功,TM会不断的重试,直到Confirm/Cancel返回成功。
特点:
- 并发度较高,无长期资源锁定。
- 开发量较大,需要提供Try/Confirm/Cancel接口。
- 一致性较好,不会发生SAGA已扣款最后又转账失败的情况
- TCC适用于订单类业务,对中间状态有约束的业务
本地消息表
写本地消息和业务操作放在一个事务里,保证了业务和发消息的原子性,要么他们全都成功,要么全都失败。
容错机制:
- 扣减余额事务失败时,事务直接回滚,无后续步骤
- 轮序生产消息失败, 增加余额事务失败都会进行重试
本地消息表的特点:
- 不支持回滚
- 轮询生产消息难实现,如果定时轮询会延长事务总时长,如果订阅binlog则开发维护困难
适用于可异步执行的业务,且后续操作无需回滚的业务