在信息时代的网络环境下,如何保证业务数据的正确性,成为重要的核心点,而数据库产品在业务数据中提供了一套完整的策略机制(原子性,一致性,隔离性,持久性),业务程序不管与数据库是单次单表交互(程序数据与数据表可能构成一个业务的原子性)还是多次多表交互(业务数据分散在多表中通过多次协议交换),事务充当了业务数据完整性很重要的角色。
本地事务 :大部分数据库自身携带事务特征,业务不需要切入业务事务的保障。
分布式事务 :各自的数据库只能保证本库的表事务,而涉及多库之间的业务数据表一致,显得难以控制实现极其复杂,如果以各自的数据库事务为基础,在此基础上构建一套事务协调系统,那么分布式数据源事务控制就变得特别简单。
Seata事务模式架构
Seata 定义了全局事务的框架。全局事务 定义为若干 分支事务 的整体协调:
- TM 向 TC 请求发起(Begin)、提交(Commit)、回滚(Rollback)全局事务。
- TM 把代表全局事务的 XID 传递到各个业务服务的分支事务上。
- RM 向 TC 注册,把分支事务关联到 XID 代表的全局事务中。
- RM 把分支事务的执行结果上报给 TC。
- TC 发送分支提交(Branch Commit)或分支回滚(Branch Rollback)命令给 RM。
Seata 的全局事务处理过程,分为两个阶段:
- 执行阶段 :执行分支业务事务,并保证执行结果满足是 可回滚的(Rollbackable)和持久化的(Durable)。
- 完成阶段: 根据执行阶段结果形成的决议,应用通过 TM 发出的全局提交或回滚的请求给 TC,TC 命令 RM 驱动 分支事务 进行 Commit 或 Rollback。
不同的事务模式区别在于:分支事务使用不同的事务模型方式达到全局事务两个阶段。
- 执行阶段 :如何执行并保证执行结果满足是可回滚的(Rollbackable)和持久化的(Durable)。
- 完成阶段: 收到TC的命令后,如何做到分支的提交或回滚
TCC 模式
一个分布式的全局事务,整体是 两阶段提交 的模型。全局事务是由若干分支事务组成的,分支事务要满足 两阶段提交 的模型要求,即需要每个分支事务都具备自己的:
- 一阶段 prepare 行为
- 二阶段 commit 或 rollback 行为
TCC模型执行阶段:
调用业务阶段:
完成阶段:
- 分支提交:调用各事务分支定义的 Confirm 方法
- 分支回滚:调用各事务分支定义的 Cancel 方法
Seata TCC 模型实现架构图
用户接入TCC,最重要的是考虑如何将自己的业务模型拆成两阶段来实现。 例如:
- 账户业务服务,将业务划分为资源(余额)检查与预留阶段 与 执行扣款或回滚阶段。 Try 方法作为一阶段准备方法(做资源的检查和预留) 在扣钱场景下,Try 要做的事情是就是检查账户余额是否充足,预留转账资金,预留的方式就是冻结 A 账户的 转账资金。 Try 方法执行之后,账号 A 余额虽然还是 100,但是其中 10 元已经被冻结了,不能被其他事务使用。 二阶段 Confirm 方法(执行真正的扣钱操作) Confirm 会使用 Try 阶段冻结的资金,执行账号扣款。Confirm 方法执行之后,账号 A 在一阶段中冻结的 10 元已经被扣除,账号 A 余额变成 70 元 。 如果二阶段是回滚的话,就需要在 Cancel 方法内释放一阶段 Try 冻结的 10 元,使账号 A 地回到初始状态,100 元全部可用。
框架核心类
- GlobalTransactionInterceptor 完成 @GlobalTransactional TM事务的管理任务
- TccActionInterceptor 完成业务Try Seata TCC 第一阶段任务的处理
- TccResourceManager 完成业务Confirm与Cancel Seata TCC 第二阶段任务的处理
备注: 用户接入 TCC 模式,相对于 AT 模式,TCC 模式对业务代码有一定的侵入性,但是 TCC 模式无 AT 模式的全局行锁,TCC 性能会比 AT 模式高很多。
Seata TCC 架构与对应数据表之间的关系
如下图表中的数据变化对应TCC业务类三个方法对应的处理状态。
Seata TCC 模型,TM客户端&RM客户端 与TC 通信架构原理图
如下图涉及了RM、TM、TC之间内部通信核心原理,属于Seata TCC核心架构实现
至于内部实现细节代码,梦塔后续跟大家“弹弹”,时间不早,你的点赞就是对我最好的支持与动力。