一.背景介绍
阿里巴巴Seata分布式事务致力于提供高性能的简单易用的解决方案,主要分为AT,TCC,SAGA和XA四种事务模式。这里主要分为三类角色:Transaction Maneger(TM),Resource Manager(RM),Transaction coordinater(TC)。其中TM主要负责事务的开启,提交与回滚。RM负责分支事务的注册,分支事务状态的汇报等,TC部署在服务端,主要负责全局与分支事务状态的记录,发起提交/回滚全局事务的请求等等。下面将分别介绍各种事务模式。
- AT模式
AT模式提供无侵入的解决方案,所有事务的发起,提交,或回滚都交由Seata托管,在两阶段完成。一阶段解析用户SQL,生成业务SQL执行镜像,先拿到全局锁,将业务数据和回滚日志记录放在同一个本地事务中提交,然后本地锁和连接资源。在二阶段进行最终提交或异常回滚,异步化提交同步删除undo_log日志记录,回滚主要通过一阶段生成的回滚日志进行反向补偿操作。
2.TCC模式
TCC模式不依赖于底层的数据资源,在一阶段调用用户自定义的prepare逻辑,在二阶段进行commit/rollback操作也同样调用执行用户自定义的逻辑。把用户自定义的事务纳入到全局事务管理中,在设计与使用时要注意允许空回滚及幂等与并发控制。
3.SAGA模式
这是一种长事务的解决方案,很多公司现有的使用也类似于此,假定一个事务有多个参与者,在事务正常执行过程中,一旦TXn发生异常,则需要补偿前面已经进行的操作,需要手动调用执行逆向业务逻辑。一阶段只用提高本地事务,性能较高,各个参与者可异步执行,实现高吞吐,但发生异常需要写大量的补偿事务代码。
二.代码流程分析
1.梳理TmClient初始化流程:
(1)启动定时器,每隔5s进行一次重连seata-server
(2) 重连时,先从file.conf中根据分组名称找到Cluster_name
(3) 根据集群名称找到server集群的ip+port列表
(4)从ip列表中选择一个用netty进行连接
2.RmClient初始化流程:(applicationId,transactionServiceGroup)
与Tm类似
ResourceManager对应实现类全路径 io.seata.rm.datasource.DataSourceManager,该类中指定了提交和回滚的方法
总结,Spring在启动时,初始化了两个客户端TmClient和RmClient
TmClient与Server通过Netty建立连接并发送消息
RmClient与Server通过Netty建立连接,负责接收二阶段提交,回滚消息并在回调器中做处理
3.事务提交过程
一阶段提交:
commit prepare:
先解析sql,获取before image,执行业务sql,生成after image,然后根据bi和ai生成undolog记录并添加到connnectionProxy的上下文中
这样可以保证任何提交的业务数据的更新一定有对应的回滚日志的存在。
commit:
由rm client向TC注册分支事务,然后执行commit动作,接收分支注册后的状态
二阶段提交/回滚:(异步)
在RMHandlerAT类中,负责接收二阶段server发回的提交或回滚请求,并作出相应的动作
4.其他注意点
@GlobalTransaction标注的方法会被GlobalTransactionalInterceptor拦截器拦截,执行invoke方法,判断执行handleGlobalTransaction方法,最终调到TransactionalTemplate的execut方法,该方法定义了标准的执行分布式事务execute,commit,rollback等标准方法。
Rm是Rm资源管理器,负责分支事务的注册,提交,上报以及回滚操作,以及全局锁的查询操作,DefaultResourceManager 会持有当前所有RM的资源管理器,进行统一调用处理,二get()方法主要施加在当前的资源管理器,主要利用SPI的机制,进行灵活加载。
ClientMessageListener消息监听器,主要处理TC发过来的指令,并对分支事务进行分支提交,回滚以及undolog的删除操作,主要是OnMessage方法,依据消息类型做出处理。