tcc-transaction深入理解

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

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

  • 首先tcc如何实现分布式服务的事务一致性的,配置使用的指南中,主要通过Compensable注解开始,首先找到注解的切面,有两个切面,tcc-transaction-spring 的 tcc-transaction.xml配置如下:
 
    
        
    
    
    
        
    

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

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

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

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

tcc-transaction深入理解_第1张图片

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

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

//事务方法的角色
public enum MethodRole {
    ROOT,//root
    CONSUMER,//消费者,框架中尚未使用
    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;//事物id
    private TransactionStatus status;//事物状态
    private TransactionType transactionType;//事物类型
    private List participants = new ArrayList();//参与者集合
....
//参与者
public class Participant implements Serializable {
    private TransactionXid xid;//事物id
    private InvocationContext confirmInvocationContext;//确认方法上下文
    private InvocationContext cancelInvocationContext;//取消方法上下文
    Class 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 normal

ResourceCoordinatorInterceptor enlistParticipant

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

tcc-transaction深入理解_第2张图片

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> allDelayCancelExceptions = new HashSet>();
        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

 

你可能感兴趣的:(java)