深入浅出 Seata 的 AT 模式
单个掉队,导致集体被动摆烂;
一、业务背景
在分布式架构中,事务管理是个无法避开的复杂问题,虽然有多种解决方案,但是需要根据业务去选择合适的;
从个人最近几年的实践经验来看,Seata 组件的 AT 模式比较常用,本文从实际的案例出发,来深入分析该模式的原理;
首先创建一个全局事务管理的接口,这里是在 Facade 服务中开启全局事务;
请求经过三个微服务,并且各个服务都进行数据源的操作,然后模拟链路成功和异常的情况,来分析不同状态的逻辑实现;
二、Seata 架构
1、核心组件
三大组件
TC:事务协调者
即 Transaction Coordinator,维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM:事务管理器
即 Transaction Manager,定义全局事务的范围,开始事务、提交事务,回滚事务。
RM:资源管理器
即 Resource Manager,管理分支事务处理的资源,向 TC 注册分支事务,报告分支事务的状态,驱动分支事务提交或回滚。
基础交互
TC 是需要独立部署的服务,TM 和 RM 是集成在服务中,三大组件相互协作,共同完成分布事务的管理;
2、AT 模式
事务模型
AT 是 Seata 默认的模式,需要基于支持本地 ACID 事务的关系型数据库;Java 应用,通过 JDBC 访问数据库;基于案例流程,先分析 AT 的事务模型;
2.1 TM 负责定义全局事务的边界,向 TC 申请,开启一个全局事务;
2.2 全局事务创建成功后,生成全局唯一的 XID;
2.3 XID 会在微服务请求链路上下文中传播;
2.4 RM 向 TC 注册分支事务,并归属到 XID 对应的全局事务进行调度;
2.5 TM 向 TC 发起相应 XID 的全局事务提交或回滚决议;
2.6 TC 完成对 XID 管理的全部分支事务提交或回滚的调度;
核心机制
执行阶段:每个微服务的请求完成后,基于本地数据库的事务能力,保证业务数据和回滚日志在同一个本地事务中提交,快速释放连接和对资源的锁定;
完成阶段:全局提交时分支事务已经完成提交,会清理回滚日志,快速结束流程;全局回滚基于 XID 和 BranchID 查询回滚日志,完成数据回滚;
数据源代理
在 AT 模式中,应用需要使用 Seata 组件中的 JDBC 代理数据源 DataSourceProxy,实现对真正目标数据源的代理访问;
三、案例分析
1、流程分析
案例的简单描述
在案例中涉及三个服务,Facade 服务开启全局事务,然后分别请求 Account 和 Quartz 服务的更新接口,通过 Quartz 接口是否抛异常来调试 AT 模式的原理;
从实际的请求执行来说,绝大多数的请求都是可以执行成功的,而 AT 模式的异步化提交极大限度的顾及全局事务的效率问题,少数失败的情况也可以通过回滚日志进行反向补偿;
2、写隔离
上述流程分析 AT 模式的原子性,即多个分支事务要么都成功要么都失败,接下来分析多个事务中的全局锁隔离机制,先看写隔离,假设 TX1 先开始;
TX1 逻辑
TX1 开始本地事务,拿到本地锁,然后执行更新操作;
TX1 本地事务提交前,需要先获取全局锁,否则无法提交;
TX1 获取全局锁并提交,释放本地锁,但未释放全局锁;
TX2 逻辑
TX2 此时开始本地事务,拿到本地锁;
TX2 执行本地事务提交前,尝试获取全局锁;
由于全局锁被 TX1 持有,TX2 会重试等待全局锁;
假设 TX1 全局提交
TX1 如果全局事务提交,会释放全局锁;
TX2 获取全局锁成功,执行本地事务提交;
假设 TX1 全局回滚
TX1 如果全局事务回滚,要重新获取数据的本地锁,进行回滚的补偿动作;
TX2 如果仍在等待全局锁,并且还持有本地锁,TX1 事务回滚失败,会不断的重试;
当 TX2 等待全局锁超时,会放弃全局锁并回滚本地事务,释放本地锁;
TX1 最终获取数据的本地锁,完成回滚动作;
在该过程中,TX1 在结束前一直持有全局锁,TX2 获取不到全局锁无法对相同的数据执行更新动作,所以避免了脏写的问题;
3、读隔离
在数据库本地隔离级别为读已提交或以上的基础上,Seata 的 AT 模式默认全局隔离级别是读未提交;如果需要全局的读已提交,可以通过SELECT FOR UPDATE
语句的代理;
该语句的执行也需要获取全局锁,如果全局锁被 TX1 持有,TX2 会释放本地锁,查询会被阻塞并进行重试,拿到全局锁读取成功后返回;
四、对比 XA 模式
XA 是一个分布式事务分段提交协议;事务管理器即 TM:作为全局事务的调度者,负责整个事务中本地资源的提交和回滚;本地资源管理器即 RM:大部分关系型数据库都实现了 XA 接口;
TM 先向所有的参与事务的 RM 发送确认请求,根据确认的结果,判断是调用 RM 的 commit 提交还是 rollback 回滚;
XA 具有强一致性,在 2 段提交的过程中,会持有资源的锁,如果是在交易下单等复杂链路中,并且并发量很高,会存在长事务风险,XA 无法满足该类高并发的场景;
而在 Seata 的 AT 模式中,在服务执行完成后,直接进行 RM 提交和资源释放,提供了对 CAP 理论相对平衡的解决方案,并且没有侵入业务工程;
五、参考源码
版权声明: 本文为 InfoQ 作者【知了一笑】的原创文章。
原文链接:【http://xie.infoq.cn/article/c6859f010e4e2bc8c05e5e9ae】。文章转载请联系作者。
评论