ByteTCC 源码分析 - 事务流程 - 补偿型事务

170 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天

org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing

completeTransactionAfterThrowing:执行业务方法失败之后完成事务的回滚工作。

commitTransactionAfterReturning:执行业务方法成功之后完成事务的提交工作。

org.springframework.transaction.support.AbstractPlatformTransactionManager#rollback

rollback:

  1. 校验事务状态是否是已完成状态
  2. 处理回滚(processRollback)

commit:

  1. 校验事务状态是否是已完成状态
  2. 处理提交(processCommit)

org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback

继承自PlatformTransactionManager,属于Spring-TX范畴

  1. triggerBeforeCompletion:事务完成之前触发扩展点
  2. status.hasSavepoint():事务状态是否存在保存点(传播机制是Nested才会有)
  3. status.isNewTransaction():事务状态是否是新事物(事务链中第一个发起事务的方法)
  4. doRollback:真正回滚
  5. 后边不重要。。。

org.springframework.transaction.jta.JtaTransactionManager#doRollback

继承自PlatformTransactionManager,属于Spring-TX范畴 UserTransaction,属于javax.transaction包。是jta规范内的组件,供开发人员继承、重载、开发、调用。通过TransactionManager(jta)作为桥梁实际操作XAResource。

TransactionStatus(Spring-TX) -> Transaction(Spring-TX) -> 
UserTransaction(javax-tx) -> TransactionManager(javax-tx)

org.bytesoft.bytetcc.UserCompensableImpl#rollback

继承自UserTransaction:

继承自UserCompensable:提供补偿型事务的接口方法。

org.bytesoft.bytetcc.TransactionManagerImpl#rollback

继承自TransactionManager(jta即javax-tx): 继承自TransactionManager(ByteTCC):

CompensableBeanFactory beanFactory:

Transaction transaction:

Transaction compensable:补偿型分布式事务

TransactionContext transactionContext:补偿型分布式事务上下文


// org.bytesoft.bytetcc.TransactionManagerImpl#rollback

// 是补偿型分布式事务上下文
if (org.bytesoft.compensable.TransactionContext.class.isInstance(transactionContext)) {
   org.bytesoft.compensable.TransactionContext compensableContext = 
         (org.bytesoft.compensable.TransactionContext) transactionContext;
   if (compensableContext.isRecoveried()) { // 
      if (compensableContext.isCompensable() == false) { // 
         throw new IllegalStateException();
      }
      compensableManager.rollback();
   } else if (compensableContext.isCompensable() == false) { // 
      transactionManager.rollback();
   } else if (compensableContext.isCompensating()) { // 
      compensableManager.rollback();
   } else if (compensableContext.isCoordinator()) { // 
      if (compensableContext.isPropagated()) { // 
         compensableManager.rollback();
      } else if (compensableContext.getPropagationLevel() > 0) { // 
         compensableManager.rollback();
      } else {
         // 咱也不知道啥意思,Debug就走到这里了。
         compensableManager.compensableRollback(); // 补偿型事务回滚
      }
   } else {
      compensableManager.rollback();
   }
} else {
   // 
   transactionManager.rollback();
}

org.bytesoft.bytetcc.CompensableManagerImpl#compensableRollback

继承自TransactionManager(jta):
继承自TransactionManager(ByteTCC):
继承自CompensableManager(ByteTCC):

总的来说依旧是TransactionManager(jta),只不过继承CompensableManager(ByteTCC)的原因,增加了补偿型事务的方法接口。

compensableRollback:补偿型事务回滚
compensableCommit:补偿型事务提交

public void compensableRollback() throws IllegalStateException, SecurityException, SystemException {
   // 获取当前线程的补偿型事务
   CompensableTransaction transaction = this.getCompensableTransactionQuietly();
   if (transaction == null) {
      throw new IllegalStateException();
   }

   // 获取事务上下文
   TransactionContext transactionContext = transaction.getTransactionContext();
   
   // 这。。。母鸡呀
   boolean coordinator = transactionContext.isCoordinator(); // 
   boolean compensable = transactionContext.isCompensable();
   boolean compensating = transactionContext.isCompensating();

   if (compensable == false) {
      throw new IllegalStateException();
   } else if (coordinator == false) {
      throw new IllegalStateException();
   } else if (compensating) {
      throw new IllegalStateException();
   }

   // 
   TransactionLock compensableLock = this.beanFactory.getCompensableLock();
   TransactionXid xid = transactionContext.getXid();
   boolean success = false;
   try {
      // 当前线程与事务解绑
      this.desociateThread();
      this.invokeCompensableRollback(transaction);
      success = true;
   } finally {
      compensableLock.unlockTransaction(xid, this.endpoint);
      if (success) {
         transaction.forgetQuietly(); // forget transaction
      } // end-if (success)
   }

}

org.bytesoft.bytetcc.CompensableManagerImpl#invokeCompensableRollback

TransactionRepository compensableRepository:
RemoteCoordinator transactionCoordinator:

org.bytesoft.bytetcc.CompensableManagerImpl#fireCompensableRollback

org.bytesoft.bytetcc.CompensableTransactionImpl#rollback

继承自TransactionListenerAdapter:
继承自TransactionListener:
继承自CompensableTransaction:
继承自Transaction(ByteTCC):
继承自CompensableContext:
继承自TransactionListener:
继承自TransactionResourceListener:

org.bytesoft.bytetcc.CompensableTransactionImpl#fireRollback

private void fireRollback() throws IllegalStateException, SystemException {
   CompensableLogger compensableLogger = this.beanFactory.getCompensableLogger();

   // 标志事务状态为回滚中
   this.transactionStatus = Status.STATUS_ROLLING_BACK;

   // 标志所有分支事务回滚
   this.markCurrentBranchTransactionRollbackIfNecessary();

   // 标志当前事务为正在补偿中
   this.transactionContext.setCompensating(true);
   
   // 更新记录一下节点事务日志归档
   compensableLogger.updateTransaction(this.getTransactionArchive());

   SystemException systemEx = null;
   try {
      // 本地节点事务回滚后,执行本地其他分支事务节点的cancel
      this.fireNativeParticipantCancel();
   } catch (SystemException ex) {
      systemEx = ex;

      logger.info("{}| cancel native branchs failed!",
            ByteUtils.byteArrayToString(this.transactionContext.getXid().getGlobalTransactionId()), ex);
   } catch (RuntimeException ex) {
      systemEx = new SystemException();
      systemEx.initCause(ex);

      logger.info("{}| cancel native branchs failed!",
            ByteUtils.byteArrayToString(this.transactionContext.getXid().getGlobalTransactionId()), ex);
   }

   try {
      // 本地节点事务回滚后,执行远程其他分支事务节点的cancel
      this.fireRemoteParticipantCancel();
   } catch (SystemException ex) {
      logger.info("{}| cancel remote branchs failed!",
            ByteUtils.byteArrayToString(this.transactionContext.getXid().getGlobalTransactionId()), ex);
      throw ex;
   } catch (RuntimeException ex) {
      logger.info("{}| cancel remote branchs failed!",
            ByteUtils.byteArrayToString(this.transactionContext.getXid().getGlobalTransactionId()), ex);
      SystemException sysEx = new SystemException();
      sysEx.initCause(ex);
      throw sysEx;
   }

   if (systemEx != null) {
      throw systemEx;
   } else {
      // 标志事务状态为已回滚
      this.transactionStatus = Status.STATUS_ROLLEDBACK;
      compensableLogger.updateTransaction(this.getTransactionArchive());
      logger.info("{}| compensable transaction rolled back!",
            ByteUtils.byteArrayToString(transactionContext.getXid().getGlobalTransactionId()));
   }

}

org.bytesoft.bytetcc.CompensableTransactionImpl#fireNativeParticipantCancel

org.bytesoft.bytetcc.CompensableTransactionImpl#fireRemoteParticipantCancel

执行远程参与者的事务提交

List<XAResourceArchive> resourceList:远程子事务资源集合


private void fireRemoteParticipantCancel() throws RollbackRequiredException, SystemException {
   boolean committedExists = false;
   boolean rolledbackExists = false;
   boolean unFinishExists = false;
   boolean errorExists = false;

   
   // 循环处理所有的XA事务资源列表
   for (int i = 0; i < this.resourceList.size(); i++) {
      XAResourceArchive current = this.resourceList.get(i);
      if (current.isCommitted()) { // 已经提交的不再处理
         committedExists = true;
         continue;
      } else if (current.isRolledback()) { // 回滚的不再处理
         rolledbackExists = true;
         continue;
      } else if (current.isReadonly()) { // 只读的不需要处理
         continue;
      }

      CompensableLogger transactionLogger = this.beanFactory.getCompensableLogger();
      XidFactory xidFactory = this.beanFactory.getCompensableXidFactory();
      // 该XA事务的事务ID,以及对应的全局事务ID
      TransactionXid branchXid = (TransactionXid) current.getXid();
      TransactionXid globalXid = xidFactory.createGlobalXid(branchXid.getGlobalTransactionId());
      try {


         // 月落乌啼霜满天
         // 江枫渔火对愁眠
         // 姑苏城外寒山寺
         // 夜半钟声到客船
         
         // 当前事务提交全局事务,核心方法......
         current.rollback(globalXid);
         rolledbackExists = true;

         current.setRolledback(true);
         current.setCompleted(true);

         logger.info("{}| cancel remote branch: {}", ByteUtils.byteArrayToString(branchXid.getGlobalTransactionId()),
               current.getDescriptor().getIdentifier());
      } catch (XAException xaex) {
         switch (xaex.errorCode) {
         case XAException.XA_HEURHAZ:
            unFinishExists = true;
            current.setHeuristic(true);
            logger.error("{}| error occurred while cancelling remote branch: {}",
                  ByteUtils.byteArrayToString(branchXid.getGlobalTransactionId()), current, xaex);
            break;
         case XAException.XA_HEURMIX:
            committedExists = true;
            rolledbackExists = true;
            current.setCommitted(true);
            current.setRolledback(true);
            current.setHeuristic(true);
            current.setCompleted(true);
            break;
         case XAException.XA_HEURCOM:
            committedExists = true;
            current.setCommitted(true);
            current.setHeuristic(true);
            current.setCompleted(true);
            break;
         case XAException.XA_HEURRB:
            rolledbackExists = true;
            current.setRolledback(true);
            current.setHeuristic(true);
            current.setCompleted(true);
            break;
         case XAException.XA_RDONLY:
            current.setReadonly(true);
            current.setCompleted(true);
            break;
         case XAException.XAER_RMFAIL:
            unFinishExists = true;
            logger.error("{}| error occurred while cancelling remote branch: {}, the remote branch is unreachable!",
                  ByteUtils.byteArrayToString(branchXid.getGlobalTransactionId()), current, xaex);
            break;
         case XAException.XAER_NOTA:
            rolledbackExists = true;
            current.setRolledback(true);
            current.setCompleted(true);
            break;
         case XAException.XAER_RMERR:
         default:
            errorExists = true;
            logger.error("{}| error occurred while cancelling remote branch: {}",
                  ByteUtils.byteArrayToString(branchXid.getGlobalTransactionId()), current, xaex);
         }
      } catch (RuntimeException rex) {
         errorExists = true;
         logger.error("{}| error occurred while cancelling remote branch: {}",
               ByteUtils.byteArrayToString(branchXid.getGlobalTransactionId()), current, rex);
      } finally {
         if (current.isCompleted()) {
            transactionLogger.updateCoordinator(current);
         }
      }
   }

   if (committedExists && rolledbackExists) {
      throw new SystemException(XAException.XA_HEURMIX);
   } else if (unFinishExists) {
      throw new RollbackRequiredException();
   } else if (errorExists) {
      throw new SystemException(XAException.XAER_RMERR);
   } else if (committedExists) {
      throw new SystemException(XAException.XA_HEURCOM);
   }
   // else if (rolledbackExists == false) { throw new SystemException(XAException.XA_RDONLY); }

}

org.bytesoft.transaction.archive.XAResourceArchive#rollback

继承自XAResource:

public void rollback(Xid ignore) throws XAException {

   if (this.readonly) {
      // ignore
   } else if (this.committed) {
      throw new XAException(XAException.XA_HEURCOM);
   } else if (this.rolledback) {
      // ignore
   } else {
      // RemoteResourceDescriptor implements XAResourceDescriptor
      descriptor.rollback(xid);
   }

}

org.bytesoft.bytejta.supports.resource.RemoteResourceDescriptor#rollback

继承自XAResourceDescriptor:
继承自XAResource:

RemoteCoordinator delegate:动态代理 SpringCloudCoordinator implements InvocationHandler

org.bytesoft.bytetcc.supports.springcloud.SpringCloudCoordinator#invoke

继承自InvocationHandler:

org.bytesoft.bytetcc.supports.springcloud.SpringCloudBeanRegistry

单例模式
Spring容器管理
getConsumeCoordinator():获取identifier对应的RemoteCoordinator代理对象。
SpringCloudCoordinator & InvocationHandler:

// org.bytesoft.bytetcc.supports.springcloud.SpringCloudCoordinator#invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   // javax.transaction.xa.XAResource
   Class<?> clazz = method.getDeclaringClass();
   // rollback
   String methodName = method.getName();
   if (Object.class.equals(clazz)) { // 
      return method.invoke(this, args);
   } else if (RemoteCoordinator.class.equals(clazz)) { // 
      if ("getIdentifier".equals(methodName)) { // 
         return this.identifier;
      } else if ("getApplication".equals(methodName)) { // 
         int firstIndex = this.identifier.indexOf(":");
         int lastIndex = this.identifier.lastIndexOf(":");
         return firstIndex <= 0 || lastIndex <= 0 || firstIndex > lastIndex //
               ? null : this.identifier.subSequence(firstIndex + 1, lastIndex);
      } else { // 
         throw new XAException(XAException.XAER_RMFAIL);
      }
   } else if (XAResource.class.equals(clazz)) { // javax.transaction.xa.XAResource
      if ("start".equals(methodName)) {
         return null; // return immediately
      } else if ("prepare".equals(methodName)) {
         return this.invokePostCoordinator(proxy, method, args);
      } else if ("commit".equals(methodName)) {
         return this.invokePostCoordinator(proxy, method, args);
      } else if ("rollback".equals(methodName)) { // rollback
         return this.invokePostCoordinator(proxy, method, args);
      } else if ("recover".equals(methodName)) {
         return this.invokeGetCoordinator(proxy, method, args);
      } else if ("forget".equals(methodName)) {
         return this.invokePostCoordinator(proxy, method, args);
      } else {
         throw new XAException(XAException.XAER_RMFAIL);
      }
   } else {
      throw new IllegalAccessException();
   }
}

org.bytesoft.bytetcc.supports.springcloud.SpringCloudCoordinator#invokePostCoordinator

基于 restTemplate 和 StringBuilder ber(http://192.168.1.6:9004/org/bytesoft/bytetcc/rollback/3e90011619ed00000182c8caf00800079d0bd649)向消费端协作者发起TCC的Cancel请求。

########## 华丽 ########## 以下是消费端协作者

org.bytesoft.bytetcc.supports.springcloud.controller.CompensableCoordinatorController#rollback

CompensableCoordinator compensableCoordinator:

org.bytesoft.bytetcc.CompensableCoordinator#rollback

获取TransactionXid globalXid

org.bytesoft.bytetcc.CompensableCoordinator#invokeRollback

根据TransactionXid globalXid 从 事务仓库 获取 CompensableTransaction transaction(CompensableHandlerInterceptor从Header中获取解析的吗???)

org.bytesoft.bytetcc.CompensableTransactionImpl#participantRollback

org.bytesoft.bytetcc.CompensableTransactionImpl#fireRollback

这不和主事务一样的吗。。。