分布式事务解决方案之TCC Transaction 下篇

TCC Transaction  框架解析

核心通过拦截器构建事务上下文,经过反射进行confirm/cancel操作。

DTO

TransactionXid (Xid: 指一个XA事务。不同的数据库要不同的 Xid(每个数据库连接(分支)一个)) : formatId(XID 的格式标识符)、 globalTransactionId(全局事务ID)、branchQualifier(分支限定符)

TransactionContext (事务上下文) : TransactionXid 、attachments(附加属性)、status(状态<TCC>)

InvocationContext(方法调用上下文):targetClass、methodName、parameterTypes、args

Terminator(终结者): InvocationContext(确认调用的上下文)、InvocationContext(取消调用的上下文)

Participant(事务参与者): TransactionXidTerminator

Transaction (事务类): TransactionXid 、TransactionType(事务类型<主事务,从事务>)、TransactionStatus(事务状态<tcc>)、retriedCount(重试次数)、 participants (参与者列表)、 attachments(附加属性).....

Transaction TransactionContext、Participant 的 TransactionXid全局事务id一致
原因:commit/cancel操作,事务管理器TransactionManager根据Xid识别,调用Participant( 参与者)下的 Terminator( 终结者)的 InvocationContext(确认/取消 上下文

配置


事务补偿注解.

/**
 * 事务补偿注解.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface Compensable {

    public String confirmMethod() default "";

    public String cancelMethod() default "";
}

TccTransactionContextAspect 可补偿事务拦截器 (PS:拦截器1)

用来构建Transaction和TransactionContext 一个主事务调用内保证Xid一致

/**
 * 可补偿事务拦截器。
 */
public class CompensableTransactionInterceptor {

    static final Logger logger = Logger.getLogger(CompensableTransactionInterceptor.class.getSimpleName());

    /**
     * 事务配置器
     */
    private TransactionConfigurator transactionConfigurator;

    /**
     * 设置事务配置器.
     * @param transactionConfigurator
     */
    public void setTransactionConfigurator(TransactionConfigurator transactionConfigurator) {
        this.transactionConfigurator = transactionConfigurator;
    }

    /**
     * 拦截补偿方法.
     * @param pjp
     * @throws Throwable
     */
    public Object interceptCompensableMethod(ProceedingJoinPoint pjp) throws Throwable {

    	// 从拦截方法的参数中获取事务上下文
        TransactionContext transactionContext = CompensableMethodUtils.getTransactionContextFromArgs(pjp.getArgs());
        
        // 计算可补偿事务方法类型
        MethodType methodType = CompensableMethodUtils.calculateMethodType(transactionContext, true);
        
        logger.debug("==>interceptCompensableMethod methodType:" + methodType.toString());

        switch (methodType) {
            case ROOT:
                return rootMethodProceed(pjp); // 主事务方法的处理
            case PROVIDER:
                return providerMethodProceed(pjp, transactionContext); // 服务提供者事务方法处理
            default:
                return pjp.proceed(); // 其他的方法都是直接执行
        }
    }

    /**
     * 主事务方法的处理.
     * @param pjp
     * @throws Throwable
     */
    private Object rootMethodProceed(ProceedingJoinPoint pjp) throws Throwable {
    	logger.debug("==>rootMethodProceed");

        transactionConfigurator.getTransactionManager().begin(); // 事务开始(创建事务日志记录,并在当前线程缓存该事务日志记录)

        Object returnValue = null; // 返回值
        try {
        	
        	logger.debug("==>rootMethodProceed try begin");
            returnValue = pjp.proceed();  // Try (开始执行被拦截的方法)
            logger.debug("==>rootMethodProceed try end");
            
        } catch (OptimisticLockException e) {
        	logger.warn("==>compensable transaction trying exception.", e);
            throw e; //do not rollback,  waiting for recovery job
        } catch (Throwable tryingException) {
            logger.warn("compensable transaction trying failed.", tryingException);
            transactionConfigurator.getTransactionManager().rollback();
            throw tryingException;
        }

        logger.info("===>rootMethodProceed begin commit()");
        transactionConfigurator.getTransactionManager().commit(); // Try检验正常后提交(事务管理器在控制提交)

        return returnValue;
    }

    /**
     * 服务提供者事务方法处理.
     * @param pjp
     * @param transactionContext
     * @throws Throwable
     */
    private Object providerMethodProceed(ProceedingJoinPoint pjp, TransactionContext transactionContext) throws Throwable {
    	
    	logger.debug("==>providerMethodProceed transactionStatus:" + TransactionStatus.valueOf(transactionContext.getStatus()).toString());

        switch (TransactionStatus.valueOf(transactionContext.getStatus())) {
            case TRYING:
            	logger.debug("==>providerMethodProceed try begin");
            	// 基于全局事务ID扩展创建新的分支事务,并存于当前线程的事务局部变量中.
                transactionConfigurator.getTransactionManager().propagationNewBegin(transactionContext);
                logger.debug("==>providerMethodProceed try end");
                return pjp.proceed();
            case CONFIRMING:
                try {
                	logger.debug("==>providerMethodProceed confirm begin");
                	// 找出存在的事务并处理.
                    transactionConfigurator.getTransactionManager().propagationExistBegin(transactionContext);
                    transactionConfigurator.getTransactionManager().commit(); // 提交
                    logger.debug("==>providerMethodProceed confirm end");
                } catch (NoExistedTransactionException excepton) {
                    //the transaction has been commit,ignore it.
                }
                break;
            case CANCELLING:
                try {
                	logger.debug("==>providerMethodProceed cancel begin");
                    transactionConfigurator.getTransactionManager().propagationExistBegin(transactionContext);
                    transactionConfigurator.getTransactionManager().rollback(); // 回滚
                    logger.debug("==>providerMethodProceed cancel end");
                } catch (NoExistedTransactionException exception) {
                    //the transaction has been rollback,ignore it.
                }
                break;
        }

        Method method = ((MethodSignature) (pjp.getSignature())).getMethod();

        return ReflectionUtils.getNullValue(method.getReturnType());
    }

}

ResourceCoordinatorInterceptor TCC事务上下文切面拦截器 (PS:拦截器2)

构建事务Transaction中的参与者(终结者)信息

/**
 * 资源协调拦截器.
 */
public class ResourceCoordinatorInterceptor {
	
	static final Logger LOG = Logger.getLogger(ResourceCoordinatorInterceptor.class.getSimpleName());

	/**
	 * 事务配置器.
	 */
    private TransactionConfigurator transactionConfigurator;

    /**
     * 设置事务配置器.
     * @param transactionConfigurator
     */
    public void setTransactionConfigurator(TransactionConfigurator transactionConfigurator) {
        this.transactionConfigurator = transactionConfigurator;
    }

    /**
     * 拦截事务上下文方法.
     * @param pjp
     * @throws Throwable
     */
    public Object interceptTransactionContextMethod(ProceedingJoinPoint pjp) throws Throwable {
    	LOG.debug("==>interceptTransactionContextMethod(ProceedingJoinPoint pjp)");
    	// 获取当前事务
        Transaction transaction = transactionConfigurator.getTransactionManager().getCurrentTransaction();
        
        // Trying(判断是否Try阶段的事务)
        if (transaction != null && transaction.getStatus().equals(TransactionStatus.TRYING)) {
        	LOG.debug("==>TransactionStatus:" + transaction.getStatus().toString());
        	// 从参数获取事务上下文
            TransactionContext transactionContext = CompensableMethodUtils.getTransactionContextFromArgs(pjp.getArgs());
            // 获取事务补偿注解
            Compensable compensable = getCompensable(pjp);
            // 计算方法类型
            MethodType methodType = CompensableMethodUtils.calculateMethodType(transactionContext, compensable != null ? true : false);
            LOG.debug("==>methodType:" + methodType.toString());
            
            switch (methodType) {
                case ROOT:
                    generateAndEnlistRootParticipant(pjp); // 生成和登记根参与者
                    break;
                case CONSUMER:
                    generateAndEnlistConsumerParticipant(pjp); // 生成并登记消费者的参与者
                    break;
                case PROVIDER:
                    generateAndEnlistProviderParticipant(pjp); // 生成并登记服务提供者的参与者
                    break;
            }
        }
        
        LOG.debug("==>pjp.proceed(pjp.getArgs())");
        return pjp.proceed(pjp.getArgs());
    }

    /**
     * 生成和登记根参与者.
     * @param pjp
     * @return
     */
    private Participant generateAndEnlistRootParticipant(ProceedingJoinPoint pjp) {
    	LOG.debug("==>generateAndEnlistRootParticipant(ProceedingJoinPoint pjp)");
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        Compensable compensable = getCompensable(pjp);
        String confirmMethodName = compensable.confirmMethod(); // 确认方法
        String cancelMethodName = compensable.cancelMethod(); // 取消方法

        Transaction transaction = transactionConfigurator.getTransactionManager().getCurrentTransaction(); // 获取当前事务

        TransactionXid xid = new TransactionXid(transaction.getXid().getGlobalTransactionId()); // 获取事务Xid
        LOG.debug("==>TransactionXid:" + TransactionXid.byteArrayToUUID(xid.getGlobalTransactionId()).toString()
        		+ "|" + TransactionXid.byteArrayToUUID(xid.getBranchQualifier()).toString());

        Class targetClass = ReflectionUtils.getDeclaringType(pjp.getTarget().getClass(), method.getName(), method.getParameterTypes());

        // 构建确认方法的提交上下文
        InvocationContext confirmInvocation = new InvocationContext(targetClass,
                confirmMethodName,
                method.getParameterTypes(), pjp.getArgs());
        
        // 构建取消方法的提交上下文
        InvocationContext cancelInvocation = new InvocationContext(targetClass,
                cancelMethodName,
                method.getParameterTypes(), pjp.getArgs());

        // 构建参与者对像
        Participant participant =
                new Participant(
                        xid,
                        new Terminator(confirmInvocation, cancelInvocation));

        transaction.enlistParticipant(participant); // 加入参与者

        TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository();
        transactionRepository.update(transaction); // 更新事务

        return participant;
    }

    /**
     * 生成并登记消费者的参与者
     * @param pjp
     * @return
     */
        private Participant generateAndEnlistConsumerParticipant(ProceedingJoinPoint pjp) {
    	LOG.debug("==>generateAndEnlistConsumerParticipant(ProceedingJoinPoint pjp)");
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();

        Transaction transaction = transactionConfigurator.getTransactionManager().getCurrentTransaction(); // 获取当前事务

        TransactionXid xid = new TransactionXid(transaction.getXid().getGlobalTransactionId()); // 获取事务Xid
        LOG.debug("==>TransactionXid:" + TransactionXid.byteArrayToUUID(xid.getGlobalTransactionId()).toString()
        		+ "|" + TransactionXid.byteArrayToUUID(xid.getBranchQualifier()).toString());
        
        // 获取事务上下文参数的位置
        int position = CompensableMethodUtils.getTransactionContextParamPosition(((MethodSignature) pjp.getSignature()).getParameterTypes());
        
        // 给服务接口的TransactionContext参数设值
        pjp.getArgs()[position] = new TransactionContext(xid, transaction.getStatus().getId()); // 构建事务上下文

        Object[] tryArgs = pjp.getArgs(); // 获取服务接口参数
        Object[] confirmArgs = new Object[tryArgs.length]; // 确认提交参数
        Object[] cancelArgs = new Object[tryArgs.length]; // 取消提交参数

        System.arraycopy(tryArgs, 0, confirmArgs, 0, tryArgs.length); // 数组拷贝
        confirmArgs[position] = new TransactionContext(xid, TransactionStatus.CONFIRMING.getId()); // 构建事务确认上下文

        System.arraycopy(tryArgs, 0, cancelArgs, 0, tryArgs.length); // 数组拷贝
        cancelArgs[position] = new TransactionContext(xid, TransactionStatus.CANCELLING.getId()); // 构建事务取消上下文

        Class targetClass = ReflectionUtils.getDeclaringType(pjp.getTarget().getClass(), method.getName(), method.getParameterTypes());
        
        // 构建确认方法的提交上下文
        InvocationContext confirmInvocation = new InvocationContext(targetClass, method.getName(), method.getParameterTypes(), confirmArgs);
        // 构建取消方法的提交上下文
        InvocationContext cancelInvocation = new InvocationContext(targetClass, method.getName(), method.getParameterTypes(), cancelArgs);

        // 构建参与者对像
        Participant participant =
                new Participant(
                        xid,
                        new Terminator(confirmInvocation, cancelInvocation));

        transaction.enlistParticipant(participant); // 加入到参与者

        TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository();

        transactionRepository.update(transaction); // 更新事务

        return participant;
    }

    /**
     * 生成并登记服务提供者的参与者
     * @param pjp
     * @return
     */
    private Participant generateAndEnlistProviderParticipant(ProceedingJoinPoint pjp) {

        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();

        Compensable compensable = getCompensable(pjp);

        String confirmMethodName = compensable.confirmMethod();
        String cancelMethodName = compensable.cancelMethod();

        Transaction transaction = transactionConfigurator.getTransactionManager().getCurrentTransaction();

        TransactionXid xid = new TransactionXid(transaction.getXid().getGlobalTransactionId());
        LOG.debug("==>TransactionXid:" + TransactionXid.byteArrayToUUID(xid.getGlobalTransactionId()).toString()
        		+ "|" + TransactionXid.byteArrayToUUID(xid.getBranchQualifier()).toString());

        Class targetClass = ReflectionUtils.getDeclaringType(pjp.getTarget().getClass(), method.getName(), method.getParameterTypes());

        // 构建确认方法的提交上下文
        InvocationContext confirmInvocation = new InvocationContext(targetClass, confirmMethodName,
                method.getParameterTypes(), pjp.getArgs());
        
        // 构建取消方法的提交上下文
        InvocationContext cancelInvocation = new InvocationContext(targetClass, cancelMethodName,
                method.getParameterTypes(), pjp.getArgs());
        
        // 事务的ID不变,参与者的分支ID是新生成的
        Participant participant =
                new Participant(
                        xid,
                        new Terminator(confirmInvocation, cancelInvocation));

        transaction.enlistParticipant(participant);

        TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository();
        transactionRepository.update(transaction);

        return participant;
    }

    /**
     * 根据切点,获取事务注解.
     * @param pjp
     * @return
     */
    private Compensable getCompensable(ProceedingJoinPoint pjp) {
    	LOG.debug("==>getCompensable(ProceedingJoinPoint pjp)");
        MethodSignature signature = (MethodSignature) pjp.getSignature(); // 获取签名
        Method method = signature.getMethod(); // 获取方法

        Compensable compensable = method.getAnnotation(Compensable.class); // 获取注解

        if (compensable == null) {
            Method targetMethod = null;
            try {
            	// 获取目标方法
                targetMethod = pjp.getTarget().getClass().getMethod(method.getName(), method.getParameterTypes());

                if (targetMethod != null) {
                    compensable = targetMethod.getAnnotation(Compensable.class);
                }

            } catch (NoSuchMethodException e) {
                compensable = null;
            }

        }
        return compensable;
    }
}

/**
 * 事务配置器接口
 */
public interface TransactionConfigurator {

	/**
	 * 获取事务管理器.
	 * @return
	 */
    public TransactionManager getTransactionManager();

    /**
     * 获取事务库.
     * @return
     */
    public TransactionRepository getTransactionRepository();

    /**
     * 获取事务恢复配置.
     * @return
     */
    public RecoverConfig getRecoverConfig();

}
**
 * TCC事务配置器.
 */
public class TccTransactionConfigurator implements TransactionConfigurator {

	/**
	 * 事务库
	 */
    @Autowired
    private TransactionRepository transactionRepository;

    /**
     * 事务恢复配置
     */
    @Autowired(required = false)
    private RecoverConfig recoverConfig = DefaultRecoverConfig.INSTANCE;

    /**
     * 根据事务配置器创建事务管理器.
     */
    private TransactionManager transactionManager = new TransactionManager(this);

    /**
     * 获取事务管理器.
     */
    @Override
    public TransactionManager getTransactionManager() {
        return transactionManager;
    }

    /**
     * 获取事务库.
     */
    @Override
    public TransactionRepository getTransactionRepository() {
        return transactionRepository;
    }

    /**
     * 获取事务恢复配置.
     */
    @Override
    public RecoverConfig getRecoverConfig() {
        return recoverConfig;
    }
}
TransactionManager  事务管理器 核心方法 begin、commit、rollback

**
 * 事务管理器.
 */
public class TransactionManager {

    static final Logger LOG = Logger.getLogger(TransactionManager.class.getSimpleName());

    /**
	 * 事务配置器
	 */
    private TransactionConfigurator transactionConfigurator;

    public TransactionManager(TransactionConfigurator transactionConfigurator) {
        this.transactionConfigurator = transactionConfigurator;
    }

    /**
     * 定义当前线程的事务局部变量.
     */
    private ThreadLocal<Transaction> threadLocalTransaction = new ThreadLocal<Transaction>();

    /**
     * 事务开始(创建事务日志记录,并将该事务日志记录存入当前线程的事务局部变量中)
     */
    public void begin() {
    	LOG.debug("==>begin()");
        Transaction transaction = new Transaction(TransactionType.ROOT); // 事务类型为ROOT:1
        LOG.debug("==>TransactionType:" + transaction.getTransactionType().toString() + ", Transaction Status:" + transaction.getStatus().toString());
        TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository();
        transactionRepository.create(transaction); // 创建事务记录,写入事务日志库
        threadLocalTransaction.set(transaction); // 将该事务日志记录存入当前线程的事务局部变量中
    }

    /**
     * 基于全局事务ID扩展创建新的分支事务,并存于当前线程的事务局部变量中.
     * @param transactionContext
     */
    public void propagationNewBegin(TransactionContext transactionContext) {

        Transaction transaction = new Transaction(transactionContext);
        LOG.debug("==>propagationNewBegin TransactionXid:" + TransactionXid.byteArrayToUUID(transaction.getXid().getGlobalTransactionId()).toString()
        		+ "|" + TransactionXid.byteArrayToUUID(transaction.getXid().getBranchQualifier()).toString());
        
        transactionConfigurator.getTransactionRepository().create(transaction);

        threadLocalTransaction.set(transaction);
    }

    /**
     * 找出存在的事务并处理.
     * @param transactionContext
     * @throws NoExistedTransactionException
     */
    public void propagationExistBegin(TransactionContext transactionContext) throws NoExistedTransactionException {
        TransactionRepository transactionRepository = transactionConfigurator.getTransactionRepository();
        Transaction transaction = transactionRepository.findByXid(transactionContext.getXid());

        if (transaction != null) {
        	
        	LOG.debug("==>propagationExistBegin TransactionXid:" + TransactionXid.byteArrayToUUID(transaction.getXid().getGlobalTransactionId()).toString()
            		+ "|" + TransactionXid.byteArrayToUUID(transaction.getXid().getBranchQualifier()).toString());
        	
            transaction.changeStatus(TransactionStatus.valueOf(transactionContext.getStatus()));
            threadLocalTransaction.set(transaction);
        } else {
            throw new NoExistedTransactionException();
        }
    }

    /**
     * 提交.
     */
    public void commit() {
    	LOG.debug("==>TransactionManager commit()");
        Transaction transaction = getCurrentTransaction();

        transaction.changeStatus(TransactionStatus.CONFIRMING);
        LOG.debug("==>update transaction status to CONFIRMING");
        transactionConfigurator.getTransactionRepository().update(transaction);

        try {
        	LOG.info("==>transaction begin commit()");
            transaction.commit();
            transactionConfigurator.getTransactionRepository().delete(transaction);
        } catch (Throwable commitException) {
            LOG.error("compensable transaction confirm failed.", commitException);
            throw new ConfirmingException(commitException);
        }
    }

    /**
     * 获取当前事务.
     * @return
     */
    public Transaction getCurrentTransaction() {
        return threadLocalTransaction.get();
    }

    /**
     * 回滚事务.
     */
    public void rollback() {

        Transaction transaction = getCurrentTransaction();
        transaction.changeStatus(TransactionStatus.CANCELLING);

        transactionConfigurator.getTransactionRepository().update(transaction);
        
        try {
        	LOG.info("==>transaction begin rollback()");
            transaction.rollback();
            transactionConfigurator.getTransactionRepository().delete(transaction);
        } catch (Throwable rollbackException) {
            LOG.error("compensable transaction rollback failed.", rollbackException);
            throw new CancellingException(rollbackException);
        }
    }
}


从服务api 引入 maven 依赖
tcc-transaction-api
TransactionContext 放在第一个参数,拦截器2才可以执行

从服务impl 引入 maven 依赖
<dependency>
<groupId> org.mengyun </groupId>
<artifactId> tcc-transaction-spring </artifactId>
</dependency>
<dependency>
<groupId> org.mengyun </groupId>
<artifactId> tcc-transaction-api </artifactId>
</dependency>

<dependency>
<groupId> org.springframework </groupId>
<artifactId> spring-context </artifactId>
</dependency>

spring-context 引入
<import resource ="classpath:tcc-transaction.xml" />

配置spring-mybatis tccDataSource ( domain、tbSuffix 根据服务命名

	<bean id="transactionRepository"
	class="org.mengyun.tcctransaction.spring.repository.SpringJdbcTransactionRepository">
		<property name="dataSource" ref="tccDataSource"/>
		<property name="domain" value="TARGET"/>
        	<property name="tbSuffix" value="_TARGET"/>
	</bean>
主服务 try
@Compensable ( confirmMethod = "confirmCompleteSuccessOrder" , cancelMethod = "cancelCompleteSuccessOrder" )
public void completeSuccessOrder (...){}

主服务confirm
@Transactional
public void confirmCompleteSuccessOrder (...){}

主服务cancel
@Transactional
public void cancelCompleteSuccessOrder (...){}

主服务调用从服务接口
void creditToAccountTcc (TransactionContext transactionContext

从服务try
void creditToAccountTcc (TransactionContext transactionContext ,..)
@Transactional ( rollbackFor = Exception. class )
@Compensable ( confirmMethod = "" , cancelMethod = "" )
public void creditToAccountTcc (TransactionContext transactionContext ... ) {}

从服务confirm
@Transactional ( rollbackFor = Exception. class )
public void confirmCreditToAccountTcc (TransactionContext transactionContext ... ) {}

从服务cancel
@Transactional ( rollbackFor = Exception. class )
public void cancelCreditToAccountTcc (TransactionContext transactionContext ... ) {}


sql
CREATE TABLE `TCC_TRANSACTION` (
  `TRANSACTION_ID` int(11) NOT NULL AUTO_INCREMENT,
  `DOMAIN` varchar(100) DEFAULT NULL,
  `GLOBAL_TX_ID` varbinary(32) NOT NULL,
  `BRANCH_QUALIFIER` varbinary(32) NOT NULL,
  `CONTENT` varbinary(8000) DEFAULT NULL,
  `STATUS` int(11) DEFAULT NULL,
  `TRANSACTION_TYPE` int(11) DEFAULT NULL,
  `RETRIED_COUNT` int(11) DEFAULT NULL,
  `CREATE_TIME` datetime DEFAULT NULL,
  `LAST_UPDATE_TIME` datetime DEFAULT NULL,
  `VERSION` int(11) DEFAULT NULL,
  PRIMARY KEY (`TRANSACTION_ID`),
  UNIQUE KEY `UX_TX_BQ` (`GLOBAL_TX_ID`,`BRANCH_QUALIFIER`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;



正向流程

1-> 调用主服务try

1.1 -> 主服务--拦截器1(TransactionContext == null && isCompensable
没有事务上下文信息,并且方法有事务注解的,为可补偿事务根方法(也就是事务发起者--ROOT)
-> 构建 Transaction
-> 保存db & threadLocal
-> pjp.proceed()

1.2 -> 主服务--拦截器2 ( Transaction status = try &&(TransactionContext == null && isCompensable ))
没有事务上下文信息,并且方法有事务注解的,为可补偿事务根方法(也就是事务发起者--ROOT)
-> 根据 ProceedingJoinPoint pjp(AspectJ) 获取类/方法/参数类型 反射得到 targetClass,Compensable标签获取方法名称 <cancelMethod,confirmMethod>,构建 Terminator(终结者)
-> 构建 Participant(事务参与者)<Transaction xid, Terminator>
-> 获取Transaction 保存 Participant
-> 更新db & threadLocal (版本和时间)
-> pjp.proceed()

1.3 -> 主服务try
-> 调用从服务try接口

1.4 -> 主服务--拦截器2 ( Transaction status = try &&(TransactionContext == null && !isCompensable ))
没有事务上下文信息,并且方法没有事务注解的,为可补偿事务服务消费者(参考者)方法(一般为被 调用的服务接口 --CONSUMER)
-> 获取 Transaction
-> 构建TransactionContext( new TransactionXid全局事务id一致
-> pjp 获取所有参数,反射ParamType 定位 TransactionContext 在 agr[] 位置并 更新
-> pjp获取所有参数 copy confiArr、cancelArr ; 并同时更新 Arr中对应TransactionContext (状态不同cancel、confirm)
-> 同 1.2构建 Terminator( 与 1.2 不同:更新参数TransactionContext ; cancelMethod,confirmMethod是接口名 )
-> 同 1.2构建 Participant
-> Transaction 保存 Participant
-> 更新db & threadLocal
-> pjp.proceed()

2 -> 调用从服务try

2.1 -> 从服务--拦截器1(TransactionContext != null && isCompensable
有事务上下文信息,并且方法有事务注解的,为可补偿事务服务提供者方法(一般为被调用的服务接口的实现方法--PROVIDER)
-> 获取 TransactionContext xid,构建 Transaction
-> 保存db & threadLocal
-> pjp.proceed()

2.2 -> 从服务--拦截器2 ( Transaction status = try &&(TransactionContext != null && isCompensable ))
有事务上下文信息,并且方法有事务注解的,为可补偿事务服务提供者方法(一般为被调用的服务接口的实现方法--PROVIDER)
-> 获取 Transaction Xid
-> pjp获取所有参数 copy confiArr、cancelArr ;
-> 同上构建 Terminator
-> 同上构建 Participant
-> Transaction 保存 Participant
-> 更新db & threadLocal
-> pjp.proceed()

3.-> 1.1 主服务--拦截器1 pjp.proceed() ,成功commit,失败rollback,异常
OptimisticLockException throw 等待回滚
3.1.1-> commit
-> 获取 Transaction 更新status (try -> confirm)
-> 调用 Transaction 的commit :遍历 Participant list ( 此处流程:主服务中的方法,从服务的接口在3.2详解)调用 Terminator 的 commit(invoke confirmInvocationContext)
-> beanFactory.getBean(targetClass) 若为空,则 invocationContext.getTargetClass().newInstance();
-> 找到要调用的目标方法target.getClass().getMethod(invocationContext.getMethodName(), invocationContext.getParameterTypes());
-> 调用服务方法,不被再次被拦截( confirm方法没有Compensable注解;Transaction status 不是try),所以直接执行远程服务 method.invoke(target, invocationContext.getArgs());
-> 删除Transaction
-> return 拦截

3.1.2-> 在 3.1 commit 遍历 Participant list 当调用到 从服务try 的接口
-> 从服务--拦截器1 TransactionContext != null && isCompensable
有事务上下文信息,并且方法有事务注解的,为可补偿事务服务提供者方法(一般为被调用的服务接口的实现方法--PROVIDER)
-> 根据 TransactionContext xid找到 Transaction ( domain过滤)
-> TransactionContext.status(Terminator的 confirmInvocationContext的参数) = confirm 执行 commit
-> 与3.1.1 操作一致,
-> 更新 Transaction 更新status (try -> confirm)
.......
.......

3.2.1-> rollback
-> 与3.1.1 操作一致, 最后 method.invoke 是 Terminator 的 cancel InvocationContext

3.2.2-> rollback
->同 3.1.2

异常流程
1 -> 启动定时任务
1.1-> 查询db 根据超过配置规定时间,没有超过最大重试次数,对应该服务domain 的 Transaction
1.2-> Transaction更新版本、时间和重试次数;
1.3 -> ransaction 是confirm状态则 进行commit操作; 是其他状态(try,cancel)全部rollback 操作
1.4 -> 1.3正常执行后 删除transaction

要求接口实现幂等性! 例如可能发生同时confirm从服务多次等情况: 主服务定时任务查询confirm状态,调用commit,调用从服务的confirm;从服务定时任务也调用了自身的confirm.....


反射涉及methods:
    /**
     * 获取事务上下文参数的位置.
     * @param parameterTypes
     * @return
     */
    public static int getTransactionContextParamPosition(Class<?>[] parameterTypes) {

        int i = -1;

        for (i = 0; i < parameterTypes.length; i++) {
            if (parameterTypes[i].equals(org.mengyun.tcctransaction.api.TransactionContext.class)) {
                break;
            }
        }
        return i;
    }

    /**
     * 从参数获取事务上下文.
     * @param args
     * @return
     */
    public static TransactionContext getTransactionContextFromArgs(Object[] args) {

        TransactionContext transactionContext = null;

        for (Object arg : args) {
            if (arg != null && org.mengyun.tcctransaction.api.TransactionContext.class.isAssignableFrom(arg.getClass())) {

                transactionContext = (org.mengyun.tcctransaction.api.TransactionContext) arg;
            }
        }

        return transactionContext;
    }

    public static Class getDeclaringType(Class aClass, String methodName, Class<?>[] parameterTypes) {

        Method method = null;


        Class findClass = aClass;

        do {
            Class[] clazzes = findClass.getInterfaces();

            for (Class clazz : clazzes) {

                try {
                    method = clazz.getDeclaredMethod(methodName, parameterTypes);
                } catch (NoSuchMethodException e) {
                    method = null;
                }

                if (method != null) {
                    return clazz;
                }
            }

            findClass = findClass.getSuperclass();

        } while (!findClass.equals(Object.class));

        return aClass;
    }


传送门 github:https://github.com/changmingxie/tcc-transaction


  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏目 "

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值