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(事务参与者):
TransactionXid、
Terminator
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;
}