介绍
分布式事务相关概念
- 事务: 并发控制的单元,是用户定义的一组操作序列,需要满足ACID属性。
- 本地事务:事务由本地资源管理器管理。
- 分布式事务:事务的操作位于不同的节点。
- 分支事务:在分布式事务中,由资源管理器管理的本地事务。
- 全局事务:一次性操作多个资源管理器完成的事务,由一组分支事务组成。
分布式相关理论
– CAP
– BASE
分布式事务实现规范
对于本地事务,可以借助DBMS系统来实现事务的管理,但是对于分布式事务,它就无能为力了。对于分布式事务,目前主要有2种思路:XA协议的强一致规范以及柔性事务的最终一致性规范。
XA
就是2阶段提交协议,应用承担事务管理器TM工作,数据库承担资源管理器RM工作,TM生成全局事务id,控制RM的提交和回滚。

柔性事务的最终一致性
该规范主要有3种实现方式,TCC、MQ事务消息、本地消息表。(还存在其他一些不常用实现方式如Saga)
- TCC:try/confirm/cancel,在try阶段锁定资源,confirm阶段进行提交,资源锁定失败执行cancel阶段释放资源。

- MQ事务消息:前提消息系统需要支持事务如RocketMQ,在本地事务执行前,发送事务消息prepare,本地事务执行成功,发送事务消息commit,实现分布式事务最终一致性。如果事务消息commit失败,RocketMQ会回查消息发送者确保消息正常提交。

- 本地消息表:跟MQ事务消息类似,区别在于MQ不支持事务消息,需要借助本地数据库的事务管理能力,将需要发送的消息和本地事务一起提交到DB,然后读取DB消息发送消费者。通过本地消息表扫描,重试发送,确保消息可以发送成功。

Seata是什么
虽然分布式事务有了这些规范,但是在业务开发过程中,需要做很多业务无关的开发,例如在应用中实现TM角色。所以不同厂商基于这些规范实现了自己的框架,以简化业务开发工作。Seata就是一种分布式事务实现框架。Seata是由阿里开源,前身为Fescar,后经过品牌升级,变身Seata。
Seata架构
系统组成
在Seata中,一个分布式事务由一个全局事务和一组分支事务组成,有以下3个组件组成:
- Transaction Coordinator(TC,事务协调器):维护全局事务和分支事务的状态,驱动全局事务提交或回滚。
- Transaction Manager(TM,事务管理器):定义全局事务的范围,开始事务、提交事务、回滚事务。
- Resource Manager(RM,资源管理器):管理分支事务上的资源,向TC注册分支事务,汇报分支事务状态,驱动分支事务的提交或回滚。
工作模式
Seata支持4种工作模式。
AT(Auto Transaction)
AT模式是Seata默认的工作模式。需要基于支持本地 ACID 事务的关系型数据库,Java 应用,通过 JDBC 访问数据库。
整体机制
该模式是XA协议的演变,XA协议是基于资源管理器实现,而AT并不是如此。AT的2个阶段分别是:
- 一阶段:业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。
- 二阶段:提交异步化,非常快速地完成;回滚通过一阶段的回滚日志进行反向补偿。

特点
- 优点:对代码无侵入;并发度高,本地锁在一阶段就会释放;不需要数据库对XA协议的支持。
- 缺点:只能用在支持ACID的关系型数据库;SQL解析还不能支持全部语法。
TCC
该模式工作分为三个阶段:prepare/commit/cancel。
整体机制
- TM向TC申请全局事务XID,传播给各个子调用。
- 子调用的所在TM向TC注册分支事务,并执行本地prepare,并向TC报告执行结果。
- TC根据各分支事务的执行结果确定二阶段是执行commit或rollback。

特点
- 优点:不依赖本地事务。
- 缺点:回滚逻辑依赖手动编码;业务侵入性较大。
Saga 模式
Saga模式是Seata提供的长事务解决方案。例如全局事务中涉及到和外部系统,既无法管理它的资源管理器,让它改造TCC也不好实行,这时就可以采用此类方案。
整体机制
在Saga模式中,业务流程中每个参与者都提交本地事务,当出现某一个参与者失败则补偿前面已经成功的参与者,一阶段正向服务和二阶段补偿服务都由业务开发实现。

上图中对于多个分支事务,省略了多次出现的 2.* 步骤。对于全局事务执行过程中业务应用宕机情况,业务应用集群中对等节点会通过从TC获取相关会话,从DB加载详细信息来恢复状态机。
特点
- 优势:一阶段提交本地事务,无锁,高性能;事件驱动架构,参与者可异步执行,高吞吐;补偿服务易于实现。
- 缺点:不保证隔离性。
XA模式
使用Seata的XA模式,需要满足分支数据库支持XA 事务,应用为java应用,且使用JDBC访问数据库。
整体机制
在 Seata 定义的分布式事务框架内,利用事务资源(数据库、消息服务等)对 XA 协议的支持,以 XA 协议的机制来管理分支事务的一种 事务模式。
- 执行阶段:业务sql在XA分支中执行,由分支事务的RM管理器管理,然后执行XA prepare。
- 完成阶段:TM根据各个分支执行结果通过TC通知各个分支执行XA commit或者XA rollback。

特点
- 优势:继承了XA协议的优势,事务具有强一致性。
- 缺点:同样继承了XA协议的劣势,由于分支事务长时间开启,并发度低。
AT模式核心实现
鉴于Seata支持的模式较多,而其默认的模式是AT,为节省篇幅,以下围绕AT模式分析其相关的核心模块实现。
事务协调器的启动
事务管理器的启动
资源管理器的启动
全局事务的工作流程
下面以一个简单的例子来说明全局事务的工作原理:
- BusinessService:发起购买服务
- StorageService:库存管理服务
购买操作实现在businessService.purchase中,purchase方法实现上通过GlobalTransaction注解,通过dubbo服务,调用了库存服务deduct方法方法,样例如下:
@GlobalTransactional(timeoutMills = , name = "dubbo-demo-tx") public void purchase(String userId, String commodityCode, int orderCount) { storageService.deduct(commodityCode, orderCount); // throw new RuntimeException("xxx"); }
成功的全局事务处理流程
失败的全局事务处理流程
写隔离实现
读隔离实现
在数据库本地隔离级别为读已提交或以上的基础上,Seata提供了读未提交,这个很好理解,全局事务提交前分支事务本地已经提交。如果想要实现读已提交,则需要在select语句后面加上for update。
总结
Seata是Java领域很强大的分布式事务框架,其支持了多种模式。其中默认支持的AT模式,相比于传统的2PC协议(基于数据库的XA协议),很好地解决了2PC长期锁资源的问题,提高了并发度。Seata支持的各个模式中,AT模式对业务零入侵实现分布式事务,对于开发者更加友好。另外Seata的Server在选择合适的存储介质时可以进行集群模式,减少单点故障影响。
本文主要参考官网和部分博客,同时阅读了AT模式实现源码,如果有不对的地方,望指出,一起讨论交流。
参考
Seata的Saga模式
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/225374.html原文链接:https://javaforall.net
