TCC 原理图如下
分为如下几步
1.业务方调用各个微服务的try()方法,执行资源检查及预留操作
2.当所有try()方法均执行成功时,对全局事务进行提交,即由事务管理器调用每个微服务的confirm()方法
当任意一个方法try()失败(预留资源不足,抑或网络异常,代码异常等任何异常),由事物管理器调用每个微服务的cancle()方法对全局事务进行回滚
try(), confirm()和cancel()方法,都需要业务方自己实现
先看下TCC的示例samples
业务调用方,通过GlobalTransactional
注解开启事务,并调用各个服务提供方的try()方法
服务提供方
TwoPhaseBusinessAction注解标记这是个TCC接口,同时指定commitMethod,rollbackMethod的名称
BusinessActionContext是TCC事务中的上下文对象
BusinessActionContextParameter注解标记的参数会在上下文中传播,即能通过BusinessActionContext对象在commit方法及cancle方法中取到该参数值
一、先看下全局GlobalTransactionScanner 的wrapIfNessary方法
从配置中获取,如果disableGlobalTransaction是生效的,直接return 返回
1.对bean进行反射解析,获取方法上面的annotation,判断是否为一个tcc的bean,如果是tcc的proxy,就创建一个TccActionInterceptor拦截器
TCC模式业务调用方和AT模式一样,需要使用GlobalTransactional
注解来开启全局事务
业务方法执行时,最终会被GlobalTransactionalInterceptor
拦截,开启一个全局事务,获得全局事务id,即xid
代码如下图
先执行事务模板的方法,调用transactionalTemplate.execute
执行方法execute
1.获取或者创建一个全局globalTransaction
2.调用getTransactionInfo,获取事务信息
2.1 循环globalTransaction的回滚方法,包装为rollbackRules,填充到事务信息transactionInfo,并且校验事务信息不为空
3.调用beginTransaction,开启事务
1.transactionManager.begin(null, null, name, timeout); 通过tmRpcClient,同步调用,底层通过channel发送请求,并且获取应答response,从中获取xid
2.然后rootContext绑定这个全局xid
3.执行业务逻辑business
4.执行出现异常,就回滚
本质上还是通过channel,同步调用tc,返回response
5.如果没有出现异常,就tx调用commit提交全局事务
分为几步
6.最后触发事务完成的操作,调用triggerAfterCompletion()
总结一下全局事务提交的大致流程
业务方调用微服务无异常,通过TM发起事务提交请求
TC接收到事务提交请求后,通过Xid找到全局事务,再取出所有的分支事务
遍历分支事务,发出分支事务提交请求
TCC资源管理器RM接收到提交请求后,从本地TCCResource缓存中根据resourceId取出对应方法bean,反射调用commit方法