各个分支事务执行完毕之后,就要提交分布式事务或者回滚分布式,只有所有的分支事务都执行成功,才能提交分布式事务;只要有一个分支事务失败,就要回滚分布式事务,分布式事务的回滚只能由事务发起者完成。
public class TransactionalTemplate {
public Object execute(TransactionalExecutor business) throws Throwable {
//省略部分代码
try {
// 2. begin transaction
/**
* 2 开始事务
* 向seata server申请zid
* 将xid绑定到当前线程
*/
beginTransaction(txInfo, tx);
Object rs = null;
try {
// Do Your Business
/**
* 做你的事情 执行目标方法 最终会执行到PreparedStatementProxy.execute()
*/
rs = business.execute();
} catch (Throwable ex) {
// 3.the needed business exception to rollback.
/**
* 3 rollback全局事务
*/
completeTransactionAfterThrowing(txInfo, tx, ex);
throw ex;
}
// 4. everything is fine, commit.
/**
* 4提交事务
*/
commitTransaction(tx);
return rs;
} finally {
//5. clear
//回调钩子函数
triggerAfterCompletion();
cleanUp();
}
} finally {
tx.resume(suspendedResourcesHolder);
}
}
}
1、提交分布式事务
public class TransactionalTemplate {
private void commitTransaction(GlobalTransaction tx) throws TransactionalExecutor.ExecutionException {
try {
//回调钩子函数
triggerBeforeCommit();
//DefaultGlobalTransaction.commit
/**
* 提交 向seata服务端发送提交请求
*/
tx.commit();
//回调钩子函数
triggerAfterCommit();
} catch (TransactionException txe) {
// 4.1 Failed to commit
throw new TransactionalExecutor.ExecutionException(tx, txe,
TransactionalExecutor.Code.CommitFailure);
}
}
}
DefaultGlobalTransaction#commit
public class DefaultGlobalTransaction implements GlobalTransaction {
public void commit() throws TransactionException {
if (role == GlobalTransactionRole.Participant) {
//全局事务的参与者
// Participant has no responsibility of committing
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Ignore Commit(): just involved in global transaction [{}]", xid);
}
return;
}
assertXIDNotNull();
int retry = COMMIT_RETRY_COUNT;
try {
while (retry > 0) {
try {
/**
* DefaultTransactionManager#commit()
* 发送提交请求
*/
status = transactionManager.commit(xid);
break;
} catch (Throwable ex) {
LOGGER.error("Failed to report global commit [{}],Retry Countdown: {}, reason: {}", this.getXid(), retry, ex.getMessage());
retry--;
if (retry == 0) {
throw new TransactionException("Failed to report global commit", ex);
}
}
}
} finally {
if (RootContext.getXID() != null && xid.equals(RootContext.getXID())) {
suspend(true);
}
}
if (LOGGER.isInfoEnabled()) {
LOGGER.info("[{}] commit status: {}", xid, status);
}
}
}
2、回滚分布式事务
public class TransactionalTemplate {
private void completeTransactionAfterThrowing(TransactionInfo txInfo, GlobalTransaction tx, Throwable ex) throws TransactionalExecutor.ExecutionException {
//roll back
//由回滚规则确定是否需要回滚
if (txInfo != null && txInfo.rollbackOn(ex)) {
try {
rollbackTransaction(tx, ex);
} catch (TransactionException txe) {
// Failed to rollback
throw new TransactionalExecutor.ExecutionException(tx, txe,
TransactionalExecutor.Code.RollbackFailure, ex);
}
} else {
// not roll back on this exception, so commit
//不需要回滚 提交分布式事务
commitTransaction(tx);
}
}
private void rollbackTransaction(GlobalTransaction tx, Throwable ex) throws TransactionException, TransactionalExecutor.ExecutionException {
//回调钩子函数
triggerBeforeRollback();
//回滚 向seata server发送全局回滚消息(重试机制)
tx.rollback();
//回调钩子函数
triggerAfterRollback();
// 3.1 Successfully rolled back
throw new TransactionalExecutor.ExecutionException(tx, GlobalStatus.RollbackRetrying.equals(tx.getLocalStatus())
? TransactionalExecutor.Code.RollbackRetrying : TransactionalExecutor.Code.RollbackDone, ex);
}
}
TransactionInfo#rollbackOn
public final class TransactionInfo implements Serializable {
//回滚规则集合 集合什么时候初始化的?
private Set<RollbackRule> rollbackRules;
public boolean rollbackOn(Throwable ex) {
RollbackRule winner = null;
int deepest = Integer.MAX_VALUE;
if (CollectionUtils.isNotEmpty(rollbackRules)) {
winner = NoRollbackRule.DEFAULT_NO_ROLLBACK_RULE;
//遍历回滚规则
for (RollbackRule rule : this.rollbackRules) {
/**
* 开发人员可以指定 在某些情况下不回滚
* 判断这个异常是有什么(class、类名)引起的
*/
int depth = rule.getDepth(ex);
if (depth >= 0 && depth < deepest) {
deepest = depth;
winner = rule;
}
}
}
return !(winner instanceof NoRollbackRule);
}
}
RollbackRule
public class RollbackRule implements Serializable {
private final String exceptionName;
public int getDepth(Throwable ex) {
return getDepth(ex.getClass(), 0);
}
private int getDepth(Class<?> exceptionClass, int depth) {
if (exceptionClass.getName().contains(this.exceptionName)) {
//找到了
return depth;
}
// If we've gone as far as we can go and haven't found it...
if (exceptionClass == Throwable.class) {
return -1;
}
//递归调用 层数+1
return getDepth(exceptionClass.getSuperclass(), depth + 1);
}
}
rollbackRules在什么时候初始化的? 在GlobalTransactionalInterceptor#handleGlobalLock方法中,
public class GlobalTransactionalInterceptor implements ConfigurationChangeListener, MethodInterceptor {
private Object handleGlobalTransaction(final MethodInvocation methodInvocation,
final GlobalTransactional globalTrxAnno) throws Throwable {
try {
return transactionalTemplate.execute(new TransactionalExecutor() {
@Override
public Object execute() throws Throwable {
//执行原始方法
return methodInvocation.proceed();
}
//自定义或者格式化生成事务的名称
public String name() {
//如果用户指定了名字 就使用用户指定的
String name = globalTrxAnno.name();
if (!StringUtils.isNullOrEmpty(name)) {
return name;
}
//没有指定就生成一个
return formatMethod(methodInvocation.getMethod());
}
//解析注解 将GlobalTransaction注解信息包装成TransactionInfo对象
@Override
public TransactionInfo getTransactionInfo() {
TransactionInfo transactionInfo = new TransactionInfo();
transactionInfo.setTimeOut(globalTrxAnno.timeoutMills());
transactionInfo.setName(name());
transactionInfo.setPropagation(globalTrxAnno.propagation());
Set<RollbackRule> rollbackRules = new LinkedHashSet<>();
//添加一些规则到rollbackRules
//哪些异常需要回滚
for (Class<?> rbRule : globalTrxAnno.rollbackFor()) {
rollbackRules.add(new RollbackRule(rbRule));
}
//哪些类引起的异常需要回滚
for (String rbRule : globalTrxAnno.rollbackForClassName()) {
rollbackRules.add(new RollbackRule(rbRule));
}
//哪些异常不需要回滚
for (Class<?> rbRule : globalTrxAnno.noRollbackFor()) {
rollbackRules.add(new NoRollbackRule(rbRule));
}
//哪些类引起的异常不需要回滚
for (String rbRule : globalTrxAnno.noRollbackForClassName()) {
rollbackRules.add(new NoRollbackRule(rbRule));
}
transactionInfo.setRollbackRules(rollbackRules);
return transactionInfo;
}
});
} catch (TransactionalExecutor.ExecutionException e) {
//省略代码
}
}
}
至此,属于seata-client的分布式事务就完成了,seata-server接收到提交或回滚分布式事务的请求后,会根据提交或回滚向各个分布式事务参与者发起分支事务提交或回滚的指令。这部分会放在后面 ,在探讨seata-server是如何处理seata-client(包括事务发起者和事务参与者)的请求的部分会进行介绍。
最后,来个全流程图