分析的项目为 https://github.com/changmingxie/tcc-transaction

在项目为dubbo搭配使用,因此全文是在dubbo服务环境进行分析。

  • 首先tcc如何实现分布式服务的事务一致性的,配置使用的指南中,主要通过Compensable注解开始,首先找到注解的切面,有两个切面,tcc-transaction-spring 的 tcc-transaction.xml配置如下:
 <!-- 初始化compensable事物切面 --><bean id="compensableTransactionAspect" class="org.mengyun.tcctransaction.spring.ConfigurableTransactionAspect"init-method="init"><property name="transactionConfigurator" ref="transactionConfigurator"/></bean><!-- 初始化compensable事物切面 --><bean id="resourceCoordinatorAspect" class="org.mengyun.tcctransaction.spring.ConfigurableCoordinatorAspect"init-method="init"><property name="transactionConfigurator" ref="transactionConfigurator"/></bean>

根据getOrder()方法的值,能知道ConfigurableTransactionAspect先行发生于ConfigurableCoordinatorAspect,这一点很重要,他们分别进行了继承操作

@Aspect
public class ConfigurableTransactionAspect extends CompensableTransactionAspect implements Ordered ....@Aspect
public class ConfigurableCoordinatorAspect extends ResourceCoordinatorAspect implements Ordered ...

代码最终回到tcc-transaction-core图示代码中,事务的一致从这两个方法和对应的拦截器拉开序幕。

下面直接通过源码中dubbo例子,来看下正常情况下tcc框架是怎么进行业务逻辑处理的。

开始之前,请先了解下关联的几个概念。

//事务方法的角色
public enum MethodRole {ROOT,//rootCONSUMER,//消费者,框架中尚未使用PROVIDER,//提供者NORMAL;//普通
}
//事务的类型
public enum TransactionType {ROOT(1),BRANCH(2);...
//事务的状态
public enum TransactionStatus {//事务的状态,各个执行阶段TRYING(1), CONFIRMING(2), CANCELLING(3);
....
//事务
public class Transaction implements Serializable {private TransactionXid xid;//事物idprivate TransactionStatus status;//事物状态private TransactionType transactionType;//事物类型private List<Participant> participants = new ArrayList<Participant>();//参与者集合
....
//参与者
public class Participant implements Serializable {private TransactionXid xid;//事物idprivate InvocationContext confirmInvocationContext;//确认方法上下文private InvocationContext cancelInvocationContext;//取消方法上下文Class<? extends TransactionContextEditor> transactionContextEditorClass;
....限于篇幅,以上只列出类中主要使用相关内容,详细内容请查看源码中的内容

代码从PaymentServiceImpl makePayment 方法开始 涉及的接口和方法有

@Compensable(confirmMethod = "confirmMakePayment", cancelMethod = "cancelMakePayment")
PaymentServiceImpl makePayment@Compensable
CapitalTradeOrderService record
@Compensable(confirmMethod = "confirmRecord", cancelMethod = "cancelRecord", transactionContextEditor = DubboTransactionContextEditor.class)
CapitalTradeOrderServiceImpl record@Compensable
RedPacketTradeOrderService record
@Compensable(confirmMethod = "confirmRecord", cancelMethod = "cancelRecord", transactionContextEditor = DubboTransactionContextEditor.class)
RedPacketTradeOrderServiceImpl record//normal即为default操作的统称
CompensableTransactionInterceptor rootMethodProceed providerMethodProceed normalResourceCoordinatorInterceptor enlistParticipant

下面将用到上面的方法来表示

https://www.processon.com/view/link/5959a5c6e4b068b0a2406f5f

详细见processon连接地址,可以看到调用方法时反复在两个拦截器间进行处理,如图为正确处理方法,如果在调用try方法时抛出异常则对ROOT transaction中的参与者依次调用cancelMethod。核心代码为CompensableTransactionInterceptor 的rootMethodProceed方法。

private Object rootMethodProceed(CompensableMethodContext compensableMethodContext) throws Throwable {Object returnValue = null;Transaction transaction = null;boolean asyncConfirm = compensableMethodContext.getAnnotation().asyncConfirm();boolean asyncCancel = compensableMethodContext.getAnnotation().asyncCancel();Set<Class<? extends Exception>> allDelayCancelExceptions = new HashSet<Class<? extends Exception>>();allDelayCancelExceptions.addAll(this.delayCancelExceptions);allDelayCancelExceptions.addAll(Arrays.asList(compensableMethodContext.getAnnotation().delayCancelExceptions()));try {//开始一个事物,使用UniqueIdentity注解配置的值,在持久层创建了一个事物transaction = transactionManager.begin(compensableMethodContext.getUniqueIdentity());logger.info(String.format("rootMethodProceed begin transaction %s",JSON.toJSONString(transaction)));try {returnValue = compensableMethodContext.proceed();} catch (Throwable tryingException) {//如果抛出异常,如果为非声明异常的子类,说明异常则进行回滚if (!isDelayCancelException(tryingException, allDelayCancelExceptions)) {logger.warn(String.format("compensable transaction trying failed. transaction content:%s", JSON.toJSONString(transaction)), tryingException);//方法非预期异常,则进行回滚transactionManager.rollback(asyncCancel);}throw tryingException;}//方法正常结束则进行事物提交transactionManager.commit(asyncConfirm);} finally {transactionManager.cleanAfterCompletion(transaction);//本地缓存中清除事物}return returnValue;}

如果,在执行confirmMethod方法和cancelMethod方法时抛出,tcc的解决方案是通过定时任务进行补偿执行,具体代码在TransactionRecovery类中,对事务状态为TransactionStatus.CONFIRMING进行再次commit或者是TransactionStatus.CANCELLING或ROOT类型的事务进行再次rollback,这里说明下ROOT类型事务,程序运行期间不管成功还是失败,ROOT类型事务都是会被删除掉,只有极端情况下,比如程序直接挂掉,重启后会对ROOT类型事务进行回滚并删除。

以上就是文章所有内容,其中还有很多细节,无法一一阐述,本人在原有tcc源码基础编写了一些注释内容,连接如下,但最好还是自己跑一遍源码中提供的例子,改变些参数,添加些日志,以便观察执行的状况。

https://github.com/patrickWuP/tcc-transaction

tcc-transaction深入理解相关推荐

  1. Oracle ITL(Interested Transaction List)理解

    ITL(Interested Transaction List) ITL是位于数据块头部的事物槽列表,它是由一系列的ITS(Interested Transaction Slot,事物槽)组成,其初始 ...

  2. hibernate的Transaction接口理解

    Transaction接口是对事物实现的一个抽象,这些实现包括JDBC事务等.Hibernate框架中的事物通过hibernate.cfg.xml文件选择JDBC.在transaction接口中定义了 ...

  3. ITL(Interested Transaction List)理解

    一.ITL描述: ITL(Interested Transaction List)是Oracle数据块内部的一个组成部分,位于数据块头(block header),itl由xid,uba,flag,l ...

  4. 面试被问分布式事务(2PC、3PC、TCC),这样解释没毛病!

    絮絮叨叨 还记得刚入行开始写Java时,接触的第一个项目是国家电网的一个业务系统,这个系统据说投资了5亿人民币进行研发,鼎盛时期研发人员一度达到过500人.项目采用当时最流行的ssh(Struts+S ...

  5. 【分布式事务】tcc-transaction分布式TCC型事务框架搭建与实战案例(基于Dubbo/Dubbox)...

    一.背景 有一定分布式开发经验的朋友都知道,产品/项目/系统最初为了能够快速迭代上线,往往不太注重产品/项目/系统的高可靠性.高性能与高扩展性,采用单体应用和单实例数据库的架构方式快速迭代开发:当产品 ...

  6. 实战!阿里神器 Seata 实现 TCC模式 解决分布式事务,真香!

    ‍ 今天这篇文章介绍一下Seata如何实现TCC事务模式,文章目录如下: 目录   什么是TCC模式? TCC(Try Confirm Cancel)方案是一种应用层面侵入业务的两阶段提交.是目前最火 ...

  7. 看了无数文章,今天终于理解这些性能指标了

    如果要问性能测试里那种技术最难,相信很多人都会说出"性能分析"这四个字.确实是,性能测试的执行是比较简单的,难的是执行完成后,如何分析这些数据.如何从一大堆数据里分析哪些数据是优秀 ...

  8. 手写基于Spring Cloud的TCC分布式事务框架

    如何简单实现TCC分布式事务框架 最近听到很多其他公司的小伙伴谈分布式事务的问题,各种业务场景都有,可能就是这两年很多公司都在往微服务发展,现在各个子系统都拆分.建设的差不多了,实现了模块化开发,但是 ...

  9. 分布式事务(2PC、3PC、TCC)

    Table of Contents 什么是分布式事务? 1.两段提交(2PC) 2.三段提交(3PC) 3.补偿事务(TCC) 什么是分布式事务? 我们看看百度上对于分布式事务的定义:分布式事务是指事 ...

  10. 事务消息大揭秘!RocketMQ、Kafka、Pulsar全方位对比

    导语 | 事务是一个程序执行单元,里面的所有操作要么全部执行成功,要么全部执行失败.RocketMQ.Kafka和Pulsar都是当今业界应用十分广泛的开源消息队列(MQ)组件,笔者在工作中遇到关于M ...

最新文章

  1. centos7下docker 部署javaweb
  2. android 简单的音乐播放器
  3. [Pyhon疫情大数据分析] 三.新闻信息抓取及词云可视化、文本聚类和LDA主题模型文本挖掘
  4. 「数据ETL」从数据民工到数据白领蜕变之旅(三)-除了Excel催化剂之外PowerQuery新物种同样值得期待...
  5. 计算机产品创新设计实践,基于TRIZ的计算机辅助机械产品创新设计研究
  6. 在矩池云上复现 CVPR 2018 LearningToCompare_FSL 环境
  7. Android 系统自带的图标
  8. Mac WebStorm 破解
  9. 单片机万年历阴阳历c语言,自己制作的单片机万年历 程序+原理图
  10. 迅雷离线下载 docker
  11. 荷兰国旗问题python_荷是什么意思 荷字五行属什么
  12. layui使用初步入门
  13. 祭祀扫墓网站php源码,斗破苍穹:不可错过的玄幻
  14. 并行编程,绝不是你想的那么简单
  15. 浅谈autolayout
  16. Codeforces1603 B. Moderate Modular Mode(数学)
  17. VC/PE乐见:简化基金注册程序,鼓励险资流向股权投资...
  18. 最后一个bate版本typora下载,typora快速上手
  19. 状态代码255 必须重启服务器,kubelet服务启动失败,错误代码255
  20. 【python初级】 windows10上升级pip

热门文章

  1. 001案例分析、常见项目管理名词
  2. UOJ449. 【集训队作业2018】喂鸽子 [概率期望,min-max容斥,生成函数]
  3. linux下uboot内存测试,uboot中的内存测试方法
  4. 基于Perclos&改进YOLOv7的疲劳驾驶DMS检测系统(源码&教程)
  5. EOJ 1864 二分图匹配
  6. 计算机网络实验(Wireshark 抓包工具使用、WinPcap 编程、协议分析流量统计程序的编写)
  7. Macbook安装pkg
  8. SONY笔记本电脑SVS131100C系统重装后Fn键功能问题
  9. java毕业生设计高考填报信息系统计算机源码+系统+mysql+调试部署+lw
  10. 牛客刷题记录之语法入门选择结构篇