1. Seata简介
Seata(Simple Extensible Autonomous Transaction Architecture) 是 阿里巴巴开源的分布式事务中间件,以高效并且对业务 0 侵入的方式,解决微服务场景下面临的分布式事务问题。
Seata支持AT、TCC、SAGA 和 XA 事务模式。
事务模式对比
分布式事务模式 | 介绍 | 技术栈 |
---|---|---|
AT 模式 | 无侵入的分布式事务解决方案,适用于不希望对业务进行改造的场景,几乎0学习成本(sql都由框架托管统一执行,会存在脏写问题) | seata、shardingsphere |
TCC 模式 | 高性能分布式事务解决方案,适用于核心系统等对性能有很高要求的场景(第一阶段会产生行锁,事务执行太久会锁行很久) | seata、service-comb |
Saga 模式 | 长事务解决方案,适用于业务流程长且需要保证事务最终一致性的业务系统(第一阶段就操作DB,会存在脏读问题) | seata、shardingsphere、service-comb |
XA模式 | 分布式强一致性的解决方案,但性能低而使用较少。 | seata、shardingsphere |
1.1 核心组件
- TC (Transaction Coordinator) - 事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。
- TM (Transaction Manager) - 事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。
- RM (Resource Manager) - 资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
1.2 全局事务和分支事务
2. Seata事务过程解析
2.1 全局事务扫描器
通过再配置文件中配置GlobalTransactionScanner
,这个实例在项目启动时会扫描所有实例,具体实现见【spring】模块。并将标注了@GlobalTransactional注解的方法织入GlobalTransactionalInterceptor的invoke方法逻辑。同时应用启动时,会初始化TM(TmRpcClient)和RM(RmRpcClient)的实例,这个时候,服务已经和TC事务控制中心勾搭上了。在往下看就涉及到TM模块的事务模板类TransactionalTemplate。
1 | <bean class="com.alibaba.fescar.spring.annotation.GlobalTransactionScanner"> |
2.2 【TM】模块启动全局事务
DefaultGlobalTransaction :全局事务具体的开启,提交、回滚动作
DefaultTransactionManager :负责使用TmRpcClient向TC控制中心发送指令,如开启全局事务(GlobalBeginRequest)、提交(GlobalCommitRequest)、回滚(GlobalRollbackRequest)、查询状态(GlobalStatusRequest)等。
以上是TM模块核心内容点,TM模块完成全局事务开启后,接下来就开始看看全局事务iD,xid是如何传递、RM组件是如何介入的
2.3 【dubbo】全局事务xid的传递
首先是xid的传递,目前已经实现了dubbo框架实现的微服务架构下的传递,其他的像spring cloud和motan等的想要实现也很容易,通过一般RPC通讯框架都有的filter机制,将xid从全局事务的发起节点传递到服务协从节点,从节点接收到后绑定到当前线程上线文环境中,用于在分支事务执行sql时判断是否加入全局事务。
2.4 【RM】模块本地资源管理的介入
3. 各事务模式介绍
3.1 AT模式(Automatic Transaction)
3.2 SAGA模式
3.3 XA模式
两阶段提交理论的一个广泛工业应用是XA协议。目前几乎所有收费的商业数据库都支持XA协议。XA协议已在业界成熟运行数十年,但目前它在互联网海量流量的应用场景中,吞吐量这个瓶颈变得十分致命,因此很少被用到。
3.4 TCC模式(Try、Confirm、Cancel)
TCC事务其实主要包含两个阶段:Try阶段、Confirm/Cancel阶段。TCC 模式需要用户根据自己的业务场景实现 Try、Confirm 和 Cancel 三个操作,事务发起方在一阶段执行 Try 方式,在二阶段提交执行 Confirm 方法,二阶段回滚执行 Cancel 方法。
TCC的核心思想是try阶段检查并预留资源,确保在confirm阶段有资源可用,这样可以最大程度的确保confirm阶段能够执行成功,避免死锁问题。
(1)try:尝试执行业务
完成所有业务检查(一致性)
预留必须业务资源(准隔离性)
(2)confirm:确认执行业务
真正执行业务
不作任何业务检查
只使用Try阶段预留的业务资源
Confirm操作必须保证幂等性
(3)cancel:取消执行业务
释放Try阶段预留的业务资源
Cancel操作必须保证幂等性
TCC具有三大特性:允许空回滚、防悬挂控制、幂等控制。
允许空回滚
当 Try 接口因丢包出现超时,或未收到Try而收到Cancel时,事务管理器会触发Cancel 接口执行回滚,如果执行时发现没有对应的事务不存在时,需要返回回滚成功,以让事务服务管理器认为已执行回滚,避免不断重试。
防悬挂控制
悬挂:Try 由于网络拥堵而超时,事务管理器生成回滚,触发 Cancel 接口,而最终又收到了 Try 接口调用,即Cancel 比 Try 接口先执行。
因允许空回滚的逻辑,事务管理器认为事务已回滚成功,则此时的 Try 接口不应该执行,否则会产生数据不一致。Cancel空回滚返回成功之前标识这条记录已回滚,Try接口先检查该事务是否被标记为回滚成功来决定是否执行。
幂等控制
幂等性:对同一个系统,使用同样的条件,一次请求和重复的多次请求对系统资源的影响是一致的。因为网络抖动或拥堵可能会超时,事务管理器会对资源进行重试操作,所以很可能一个业务操作会被重复调用,为了不因为重复调用而多次占用资源,需要在服务设计时进行幂等控制。
4. TCC二阶段异步提交功能实现
4.1 总体思路
修改tcc模块和server模块的相关代码,参考异步提交的实现,完成异步回滚特性,通过异步操作提升回滚性能,从而降低全局回滚的时间成本。
同步全局回滚时,跳过可异步执行的分支,将它们交由handleAsyncRollbacking()来处理。特性的实现主要涉及以下内容:
为分支调用过程的方法添加rollbackType参数,以及对应的日志。
实现handleAsyncRollbacking()的处理逻辑。
通过默认参数保证不同版本之间的兼容性问题。
4.2 方案设计
修改TCC的注解@TwoPhaseBusinessAction,添加TCCRollbackType rollbackType() default TCCRollbackType.SyncRollback
分支注册接口,添加参数TCCRollbackType rollbackType,且RPC交易时的序列化中,添加对该参数的序列化
TC端三种store模式,添加对rollbackType的持久化功能。db模式添加字段rollback_type
同步全局回滚时,将可异步执行的分支加入到待处理集合中
实现handleAsyncRollbacking()的处理逻辑:
- 配置:修改server模块,使该方法由异步定时任务触发。
- 算法逻辑:获取待异步处理的分支,枚举回滚分支,调用doGlobalRollback方法执行回滚操作。
4.3 方案实现
首先,学习异步提交的代码接口设计,设计异步回滚操作的代码接口,参考其实现完成TCC异步回滚的特性。其次,编写的测试用例,保证功能的正常执行,在测试时需要注意不同版本之间的兼容性,保证高版本兼容低版本。最后,撰写方案测试和使用文档。
Reference:
[1] https://seata.io/zh-cn/blog/seata-analysis-simple.html