前言
最近在看分布式事务相关的实现方案,涉及到的模式比较多,觉得有必要梳理下,用于后续涉及到分布式事务使用时的方法决策。
基于个人理解,本文的模式主要分两类:理论型和实践型
- 理论型:经典的两阶段提交(XA)、经典的TCC模式,理论型更多的是作为实践型的思想
- 实践型:又可以分为不回滚主事务型(本地消息表、事务消息、最大努力通知),以及可回滚主事务型(Seata的AT TCC及saga、以及蚂蚁的DTS模式)
本文主要是对各种模式的概念及使用做一个入门。限于个人认知,如有描述不正确的地方欢迎指正。
经典的两阶段提交(XA)
XA 的全称是 eXtended Architecture,由X/Open组织提出,是关于分布式事务处理 (DTP)的规范。
XA通过二阶段提交协议保证强一致性,中间的操作要么全部成功,要么全部失败。
大致的流程:
- 第一阶段(prepare):事务管理器向所有本地资源管理器发起请求,询问是否是 ready 状态,所有参与者都将本事务能否成功的信息反馈发给协调者;第一阶段需要做资源的预锁定,手段可以是在表中增加预锁定字段,如转账场景下的冻结金额
- 第二阶段 (commit/rollback):事务管理器根据所有本地资源管理器的反馈,先在本地持久化事务状态,然后通知所有本地资源管理器,步调一致地在所有分支上提交或者回滚。commit的话,资源管理器正式完成操作,并释放在整个事务期间占用的资源,如冻结金额变成正式扣款;rollback的话,如冻结金额扣掉回滚的金额。
存在的问题:
- 同步阻塞:当参与事务者存在占用公共资源的情况,其中一个占用了资源,其他事务参与者就只能阻塞等待资源释放,处于阻塞状态。
- 单点故障:一旦事务管理器出现故障,整个系统不可用
- 数据不一致:在阶段二,如果事务管理器只发送了部分 commit 消息,此时网络发生异常,那么只有部分参与者接收到 commit 消息,也就是说只有部分参与者提交了事务,使得系统数据不一致。
- 不确定性:当协事务管理器发送 commit 之后,并且此时只有一个参与者收到了 commit,那么当该参与者与事务管理器同时宕机之后,重新选举的事务管理器无法确定该条消息是否提交成功。
以上是经典的两阶段提交,而现在工程实践中使用到的模式大多基于两阶段提交的思想再做优化,如蚂蚁DTS、seata at、seata tcc等。两阶段提交的思想简单来说就是第一阶段先预占/锁定,第二阶段进行提交或回滚。
经典的TCC
TCC