分析的项目为 https://github.com/changmingxie/tcc-transaction
在项目为dubbo搭配使用,因此全文是在dubbo服务环境进行分析。
根据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,//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 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 normal
ResourceCoordinatorInterceptor 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> 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