十三、Seata分布式事务源码解析

一、自动配置类SeataAutoConfiguration

SeataAutoConfiguration 自动配置类,注册GlobalTransactionScanner组件。

@Bean
@DependsOn({BEAN_NAME_SPRING_APPLICATION_CONTEXT_PROVIDER, BEAN_NAME_FAILURE_HANDLER})
@ConditionalOnMissingBean(GlobalTransactionScanner.class)
public GlobalTransactionScanner globalTransactionScanner(SeataProperties seataProperties, FailureHandler failureHandler) {
	if (LOGGER.isInfoEnabled()) {
		LOGGER.info("Automatically configure Seata");
	}
	//创建GlobalTransactionScanner
	return new GlobalTransactionScanner(seataProperties.getApplicationId(), seataProperties.getTxServiceGroup(), failureHandler);
}

GlobalTransactionScanner 实现InitializingBean接口,所以会调用afterPropertiesSet方法。

@Override
public void afterPropertiesSet() {
	ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,
		(ConfigurationChangeListener)this);
	if (disableGlobalTransaction) {
		if (LOGGER.isInfoEnabled()) {
			LOGGER.info("Global transaction is disabled.");
		}
		return;
	}
	if (initialized.compareAndSet(false, true)) {
	    //初始化Client
		initClient();
	}
}

初始化Client,initClient方法

 private void initClient() {
	if (LOGGER.isInfoEnabled()) {
		LOGGER.info("Initializing Global Transaction Clients ... ");
	}
	if (StringUtils.isNullOrEmpty(applicationId) || StringUtils.isNullOrEmpty(txServiceGroup)) {
		throw new IllegalArgumentException(String.format("applicationId: %s, txServiceGroup: %s", applicationId, txServiceGroup));
	}
	//初始化TM
	TMClient.init(applicationId, txServiceGroup, accessKey, secretKey);
	if (LOGGER.isInfoEnabled()) {
		LOGGER.info("Transaction Manager Client is initialized. applicationId[{}] txServiceGroup[{}]", applicationId, txServiceGroup);
	}
	//初始化RM
	RMClient.init(applicationId, txServiceGroup);
	if (LOGGER.isInfoEnabled()) {
		LOGGER.info("Resource Manager is initialized. applicationId[{}] txServiceGroup[{}]", applicationId, txServiceGroup);
	}

	if (LOGGER.isInfoEnabled()) {
		LOGGER.info("Global Transaction Clients are initialized. ");
	}
	registerSpringShutdownHook();

}

TMClient.init 方法:

public static void init(String applicationId, String transactionServiceGroup, String accessKey, String secretKey) {
	TmNettyRemotingClient tmNettyRemotingClient = TmNettyRemotingClient.getInstance(applicationId, transactionServiceGroup, accessKey, secretKey);
	tmNettyRemotingClient.init();
}

RMClient.init方法:

public static void init(String applicationId, String transactionServiceGroup) {
	RmNettyRemotingClient rmNettyRemotingClient = RmNettyRemotingClient.getInstance(applicationId, transactionServiceGroup);
	rmNettyRemotingClient.setResourceManager(DefaultResourceManager.get());
	rmNettyRemotingClient.setTransactionMessageHandler(DefaultRMHandler.get());
	rmNettyRemotingClient.init();
}

启动两个netty客户端,TM 和 RM,那么netty服务端在seata中什么位置启动的?

二、seata启动

ServerRunner实现CommandLineRunner接口,所以在容器refresh后调用CommandLineRunner的run方法:

@Override
public void run(String... args) {
	try {
		long start = System.currentTimeMillis();
		//启动server
		Server.start(args);
		started = true;

		long cost = System.currentTimeMillis() - start;
		LOGGER.info("seata server started in {} millSeconds", cost);
	} catch (Throwable e) {
		started = Boolean.FALSE;
		LOGGER.error("seata server start error: {} ", e.getMessage(), e);
		System.exit(-1);
	}
}

Server的start方法,创建NettyRemotingServer服务端,创建TC

public static void start(String[] args) {
	// create logger
	final Logger logger = LoggerFactory.getLogger(Server.class);

	//initialize the parameter parser
	//Note that the parameter parser should always be the first line to execute.
	//Because, here we need to parse the parameters needed for startup.
	ParameterParser parameterParser = new ParameterParser(args);

	//initialize the metrics
	MetricsManager.get().init();

	System.setProperty(ConfigurationKeys.STORE_MODE, parameterParser.getStoreMode());

	ThreadPoolExecutor workingThreads = new ThreadPoolExecutor(NettyServerConfig.getMinServerPoolSize(),
			NettyServerConfig.getMaxServerPoolSize(), NettyServerConfig.getKeepAliveTime(), TimeUnit.SECONDS,
			new LinkedBlockingQueue<>(NettyServerConfig.getMaxTaskQueueSize()),
			new NamedThreadFactory("ServerHandlerThread", NettyServerConfig.getMaxServerPoolSize()), new ThreadPoolExecutor.CallerRunsPolicy());
    //创建NettyRemotingServer
	NettyRemotingServer nettyRemotingServer = new NettyRemotingServer(workingThreads);
	UUIDGenerator.init(parameterParser.getServerNode());
	//log store mode : file, db, redis
	SessionHolder.init(parameterParser.getSessionStoreMode());
	LockerManagerFactory.init(parameterParser.getLockStoreMode());
	//创建TC 事务协调器,绑定netty信息
	DefaultCoordinator coordinator = DefaultCoordinator.getInstance(nettyRemotingServer);
	//初始化
	coordinator.init();
	nettyRemotingServer.setHandler(coordinator);

	// let ServerRunner do destroy instead ShutdownHook, see https://github.com/seata/seata/issues/4028
	ServerRunner.addDisposable(coordinator);

	//127.0.0.1 and 0.0.0.0 are not valid here.
	if (NetUtil.isValidIp(parameterParser.getHost(), false)) {
		XID.setIpAddress(parameterParser.getHost());
	} else {
		String preferredNetworks = ConfigurationFactory.getInstance().getConfig(REGISTRY_PREFERED_NETWORKS);
		if (StringUtils.isNotBlank(preferredNetworks)) {
			XID.setIpAddress(NetUtil.getLocalIp(preferredNetworks.split(REGEX_SPLIT_CHAR)));
		} else {
			XID.setIpAddress(NetUtil.getLocalIp());
		}
	}
	//注册处理器,启动nettyserver
	nettyRemotingServer.init();
}

DefaultCoordinator的init()方法,初始化一批定时任务


public void init() {
    //重试回滚
	retryRollbacking.scheduleAtFixedRate(
		() -> SessionHolder.distributedLockAndExecute(RETRY_ROLLBACKING, this::handleRetryRollbacking), 0,
		ROLLBACKING_RETRY_PERIOD, TimeUnit.MILLISECONDS);
    //重试提交
	retryCommitting.scheduleAtFixedRate(
		() -> SessionHolder.distributedLockAndExecute(RETRY_COMMITTING, this::handleRetryCommitting), 0,
		COMMITTING_RETRY_PERIOD, TimeUnit.MILLISECONDS);
	//异步提交
	asyncCommitting.scheduleAtFixedRate(
		() -> SessionHolder.distributedLockAndExecute(ASYNC_COMMITTING, this::handleAsyncCommitting), 0,
		ASYNC_COMMITTING_RETRY_PERIOD, TimeUnit.MILLISECONDS);
	//异步超时检查
	timeoutCheck.scheduleAtFixedRate(
		() -> SessionHolder.distributedLockAndExecute(TX_TIMEOUT_CHECK, this::timeoutCheck), 0,
		TIMEOUT_RETRY_PERIOD, TimeUnit.MILLISECONDS);
	//undoLog 删除
	undoLogDelete.scheduleAtFixedRate(
		() -> SessionHolder.distributedLockAndExecute(UNDOLOG_DELETE, this::undoLogDelete),
		UNDO_LOG_DELAY_DELETE_PERIOD, UNDO_LOG_DELETE_PERIOD, TimeUnit.MILLISECONDS);
}

三、GlobalTransactionScanner组件

GlobalTransactionScanner 继承AbstractAutoProxyCreator,实现SmartInstantiationAwareBeanPostProcessor后置处理器。
所以会调用初始化后方法,最后调用wrapIfNecessary方法,创建全局事务拦截器GlobalTransactionalInterceptor

@Override
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	try {
		synchronized (PROXYED_SET) {
			if (PROXYED_SET.contains(beanName)) {
				return bean;
			}
			interceptor = null;
			//check TCC proxy
			if (TCCBeanParserUtils.isTccAutoProxy(bean, beanName, applicationContext)) {
				//创建TCC拦截器
				interceptor = new TccActionInterceptor(TCCBeanParserUtils.getRemotingDesc(beanName));
				ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,
					(ConfigurationChangeListener)interceptor);
			} else {
				Class<?> serviceInterface = SpringProxyUtils.findTargetClass(bean);
				Class<?>[] interfacesIfJdk = SpringProxyUtils.findInterfaces(bean);
				//不存在@GlobalTransactional注解,就直接返回了
				if (!existsAnnotation(new Class[]{serviceInterface})
					&& !existsAnnotation(interfacesIfJdk)) {
					return bean;
				}
				
				if (interceptor == null) {
					if (globalTransactionalInterceptor == null) {
					    //创建全局事务拦截器
						globalTransactionalInterceptor = new GlobalTransactionalInterceptor(failureHandlerHook);
						ConfigurationCache.addConfigListener(
							ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,
							(ConfigurationChangeListener)globalTransactionalInterceptor);
					}
					interceptor = globalTransactionalInterceptor;
				}
			}

			LOGGER.info("Bean[{}] with name [{}] would use interceptor [{}]", bean.getClass().getName(), beanName, interceptor.getClass().getName());
			if (!AopUtils.isAopProxy(bean)) {
				bean = super.wrapIfNecessary(bean, beanName, cacheKey);
			} else {
				AdvisedSupport advised = SpringProxyUtils.getAdvisedSupport(bean);
				Advisor[] advisor = buildAdvisors(beanName, getAdvicesAndAdvisorsForBean(null, null, null));
				for (Advisor avr : advisor) {
					advised.addAdvisor(0, avr);
				}
			}
			PROXYED_SET.add(beanName);
			return bean;
		}
	} catch (Exception exx) {
		throw new RuntimeException(exx);
	}
}


四、AOP方法拦截

客户端的业务方法被调用的时候,aop会调用GlobalTransactionalInterceptor的invoke方法。

@Override
public Object invoke(final MethodInvocation methodInvocation) throws Throwable {
	Class<?> targetClass =
		methodInvocation.getThis() != null ? AopUtils.getTargetClass(methodInvocation.getThis()) : null;
	Method specificMethod = ClassUtils.getMostSpecificMethod(methodInvocation.getMethod(), targetClass);
	if (specificMethod != null && !specificMethod.getDeclaringClass().equals(Object.class)) {
		final Method method = BridgeMethodResolver.findBridgedMethod(specificMethod);
		final GlobalTransactional globalTransactionalAnnotation =
			getAnnotation(method, targetClass, GlobalTransactional.class);
		final GlobalLock globalLockAnnotation = getAnnotation(method, targetClass, GlobalLock.class);
		boolean localDisable = disable || (degradeCheck && degradeNum >= degradeCheckAllowTimes);
		if (!localDisable) {
			if (globalTransactionalAnnotation != null) {
			    //处理全局事务
				return handleGlobalTransaction(methodInvocation, globalTransactionalAnnotation);
			} else if (globalLockAnnotation != null) {
				return handleGlobalLock(methodInvocation, globalLockAnnotation);
			}
		}
	}
	return methodInvocation.proceed();
}

handleGlobalTransaction方法,处理全局事务:

Object handleGlobalTransaction(final MethodInvocation methodInvocation,
	final GlobalTransactional globalTrxAnno) throws Throwable {
	boolean succeed = true;
	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());
			}
			//获取事务信息
			@Override
			public TransactionInfo getTransactionInfo() {
				// reset the value of timeout
				int timeout = globalTrxAnno.timeoutMills();
				if (timeout <= 0 || timeout == DEFAULT_GLOBAL_TRANSACTION_TIMEOUT) {
					timeout = defaultGlobalTransactionTimeout;
				}

				TransactionInfo transactionInfo = new TransactionInfo();
				transactionInfo.setTimeOut(timeout);
				transactionInfo.setName(name());
				transactionInfo.setPropagation(globalTrxAnno.propagation());
				transactionInfo.setLockRetryInternal(globalTrxAnno.lockRetryInternal());
				transactionInfo.setLockRetryTimes(globalTrxAnno.lockRetryTimes());
				Set<RollbackRule> rollbackRules = new LinkedHashSet<>();
				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) {
		TransactionalExecutor.Code code = e.getCode();
		switch (code) {
			case RollbackDone:
				throw e.getOriginalException();
			case BeginFailure:
				succeed = false;
				failureHandler.onBeginFailure(e.getTransaction(), e.getCause());
				throw e.getCause();
			case CommitFailure:
				succeed = false;
				failureHandler.onCommitFailure(e.getTransaction(), e.getCause());
				throw e.getCause();
			case RollbackFailure:
				failureHandler.onRollbackFailure(e.getTransaction(), e.getOriginalException());
				throw e.getOriginalException();
			case RollbackRetrying:
				failureHandler.onRollbackRetrying(e.getTransaction(), e.getOriginalException());
				throw e.getOriginalException();
			default:
				throw new ShouldNeverHappenException(String.format("Unknown TransactionalExecutor.Code: %s", code));
		}
	} finally {
		if (degradeCheck) {
			EVENT_BUS.post(new DegradeCheckEvent(succeed));
		}
	}
}

transactionalTemplate.execute方法,是核心的方法,主要是全局事务的开启,执行业务代码,提交全局事务或者回滚全局事务

execute(TransactionalExecutor business) throws Throwable {
	// 1. 获取事务信息
	TransactionInfo txInfo = business.getTransactionInfo();
	if (txInfo == null) {
		throw new ShouldNeverHappenException("transactionInfo does not exist");
	}
	// 1.1 获取当前事务,如果不是空,则是GlobalTransactionRole.Participant的角色
	GlobalTransaction tx = GlobalTransactionContext.getCurrent();

	// 1.2 处理事务的隔离级别.
	Propagation propagation = txInfo.getPropagation();
	SuspendedResourcesHolder suspendedResourcesHolder = null;
	try {
		switch (propagation) {
			case NOT_SUPPORTED:
				// If transaction is existing, suspend it.
				if (existingTransaction(tx)) {
					suspendedResourcesHolder = tx.suspend();
				}
				// Execute without transaction and return.
				return business.execute();
			case REQUIRES_NEW:
				// If transaction is existing, suspend it, and then begin new transaction.
				if (existingTransaction(tx)) {
					suspendedResourcesHolder = tx.suspend();
					tx = GlobalTransactionContext.createNew();
				}
				// Continue and execute with new transaction
				break;
			case SUPPORTS:
				// If transaction is not existing, execute without transaction.
				if (notExistingTransaction(tx)) {
					return business.execute();
				}
				// Continue and execute with new transaction
				break;
			case REQUIRED:
				// If current transaction is existing, execute with current transaction,
				// else continue and execute with new transaction.
				break;
			case NEVER:
				// If transaction is existing, throw exception.
				if (existingTransaction(tx)) {
					throw new TransactionException(
						String.format("Existing transaction found for transaction marked with propagation 'never', xid = %s"
								, tx.getXid()));
				} else {
					// Execute without transaction and return.
					return business.execute();
				}
			case MANDATORY:
				// If transaction is not existing, throw exception.
				if (notExistingTransaction(tx)) {
					throw new TransactionException("No existing transaction found for transaction marked with propagation 'mandatory'");
				}
				// Continue and execute with current transaction.
				break;
			default:
				throw new TransactionException("Not Supported Propagation:" + propagation);
		}

		//  如果事务空的,则是 GlobalTransactionRole.Launcher角色.
		if (tx == null) {
		    //创建一个新的全局事务 
			tx = GlobalTransactionContext.createNew();
		}

		// set current tx config to holder
		GlobalLockConfig previousConfig = replaceGlobalLockConfig(txInfo);

		try {
			// 角色是 GlobalTransactionRole.Launcher, 则发送请求到 TC,不是Launcher,不做什么
			beginTransaction(txInfo, tx);

			Object rs;
			try {
				// 执行我们的业务方法
				rs = business.execute();
			} catch (Throwable ex) {
				// 全局事务回滚
				completeTransactionAfterThrowing(txInfo, tx, ex);
				throw ex;
			}

			//  全局事务提交.
			commitTransaction(tx);

			return rs;
		} finally {
			//5. clear
			resumeGlobalLockConfig(previousConfig);
			triggerAfterCompletion();
			cleanUp();
		}
	} finally {
		// If the transaction is suspended, resume it.
		if (suspendedResourcesHolder != null) {
			tx.resume(suspendedResourcesHolder);
		}
	}
}

1、开启全局事务 beginTransaction

private void beginTransaction(TransactionInfo txInfo, GlobalTransaction tx) throws TransactionalExecutor.ExecutionException {
	try {
		triggerBeforeBegin();
		//事务开启
		tx.begin(txInfo.getTimeOut(), txInfo.getName());
		triggerAfterBegin();
	} catch (TransactionException txe) {
		throw new TransactionalExecutor.ExecutionException(tx, txe,
			TransactionalExecutor.Code.BeginFailure);

	}
}

begin方法,只有Launcher角色才可以,发起全局事务

public void begin(int timeout, String name) throws TransactionException {
    //不是Launcher角色就返回了。
	if (role != GlobalTransactionRole.Launcher) {
		assertXIDNotNull();
		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("Ignore Begin(): just involved in global transaction [{}]", xid);
		}
		return;
	}
	assertXIDNull();
	String currentXid = RootContext.getXID();
	if (currentXid != null) {
		throw new IllegalStateException("Global transaction already exists," +
			" can't begin a new global transaction, currentXid = " + currentXid);
	}
	//全局事务开启,获得全局事务id
	xid = transactionManager.begin(null, null, name, timeout);
	status = GlobalStatus.Begin;
	//绑定全局事务id
	RootContext.bind(xid);
	if (LOGGER.isInfoEnabled()) {
		LOGGER.info("Begin new global transaction [{}]", xid);
	}
}

DefaultTransactionManager的begin方法,rpc调用seata获取全局事务ID:

@Override
public String begin(String applicationId, String transactionServiceGroup, String name, int timeout)
	throws TransactionException {
	GlobalBeginRequest request = new GlobalBeginRequest();
	request.setTransactionName(name);
	request.setTimeout(timeout);
	//同步调用seata服务端,TmNettyRemotingClient的rpc调用
	GlobalBeginResponse response = (GlobalBeginResponse) syncCall(request);
	if (response.getResultCode() == ResultCode.Failed) {
		throw new TmTransactionException(TransactionExceptionCode.BeginFailed, response.getMsg());
	}
	//返回全局事务id
	return response.getXid();
}

syncCall方法发起rpc请求


private AbstractTransactionResponse syncCall(AbstractTransactionRequest request) throws TransactionException {
	try {
		return (AbstractTransactionResponse) TmNettyRemotingClient.getInstance().sendSyncRequest(request);
	} catch (TimeoutException toe) {
		throw new TmTransactionException(TransactionExceptionCode.IO, "RPC timeout", toe);
	}
}

seata服务端DefaultCoordinator.doGlobalBegin方法处理

@Override
protected void doGlobalBegin(GlobalBeginRequest request, GlobalBeginResponse response, RpcContext rpcContext)
		throws TransactionException {
	//core.begin 开启全局事务session,返回xid
	response.setXid(core.begin(rpcContext.getApplicationId(), rpcContext.getTransactionServiceGroup(),
			request.getTransactionName(), request.getTimeout()));
	if (LOGGER.isInfoEnabled()) {
		LOGGER.info("Begin new global transaction applicationId: {},transactionServiceGroup: {}, transactionName: {},timeout:{},xid:{}",
				rpcContext.getApplicationId(), rpcContext.getTransactionServiceGroup(), request.getTransactionName(), request.getTimeout(), response.getXid());
	}
}

DefaultCore的begin方法:

@Override
public String begin(String applicationId, String transactionServiceGroup, String name, int timeout)
	throws TransactionException {
	//创建GlobalSession,生成XID(ip:端口:uuid)
	GlobalSession session = GlobalSession.createGlobalSession(applicationId, transactionServiceGroup, name,
		timeout);
	MDC.put(RootContext.MDC_KEY_XID, session.getXid());
	session.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
	//开启session,我们是db模式,则写入数据库
	session.begin();

	// transaction start event
	MetricsPublisher.postSessionDoingEvent(session, false);

	return session.getXid();
}

GlobalSession.begin方法:

@Override
public void begin() throws TransactionException {
	this.status = GlobalStatus.Begin;
	this.beginTime = System.currentTimeMillis();
	this.active = true;
	for (SessionLifecycleListener lifecycleListener : lifecycleListeners) {
	    //核心方法
		lifecycleListener.onBegin(this);
	}
}

会调用AbstractSessionManager的onBegin方法,它调用addGlobalSession

@Override
public void addGlobalSession(GlobalSession session) throws TransactionException {
	if (LOGGER.isDebugEnabled()) {
		LOGGER.debug("MANAGER[{}] SESSION[{}] {}", name, session, LogOperation.GLOBAL_ADD);
	}
	//持久化,操作是GLOBAL_ADD
	writeSession(LogOperation.GLOBAL_ADD, session);
}

writeSession方法

private void writeSession(LogOperation logOperation, SessionStorable sessionStorable) throws TransactionException {
	//根据不同的存储模式,写入session,我们是db模式,则写入数据库
	if (!transactionStoreManager.writeSession(logOperation, sessionStorable)) {
		if (LogOperation.GLOBAL_ADD.equals(logOperation)) {
			throw new GlobalTransactionException(TransactionExceptionCode.FailedWriteSession,
				"Fail to store global session");
		} else if (LogOperation.GLOBAL_UPDATE.equals(logOperation)) {
			throw new GlobalTransactionException(TransactionExceptionCode.FailedWriteSession,
				"Fail to update global session");
		} else if (LogOperation.GLOBAL_REMOVE.equals(logOperation)) {
			throw new GlobalTransactionException(TransactionExceptionCode.FailedWriteSession,
				"Fail to remove global session");
		} else if (LogOperation.BRANCH_ADD.equals(logOperation)) {
			throw new BranchTransactionException(TransactionExceptionCode.FailedWriteSession,
				"Fail to store branch session");
		} else if (LogOperation.BRANCH_UPDATE.equals(logOperation)) {
			throw new BranchTransactionException(TransactionExceptionCode.FailedWriteSession,
				"Fail to update branch session");
		} else if (LogOperation.BRANCH_REMOVE.equals(logOperation)) {
			throw new BranchTransactionException(TransactionExceptionCode.FailedWriteSession,
				"Fail to remove branch session");
		} else {
			throw new BranchTransactionException(TransactionExceptionCode.FailedWriteSession,
				"Unknown LogOperation:" + logOperation.name());
		}
	}
}

DataBaseTransactionStoreManager的writeSession方法

@Override
public boolean writeSession(LogOperation logOperation, SessionStorable session) {
	if (LogOperation.GLOBAL_ADD.equals(logOperation)) {
	    //GLOBAL_ADD 操作
		return logStore.insertGlobalTransactionDO(SessionConverter.convertGlobalTransactionDO(session));
	} else if (LogOperation.GLOBAL_UPDATE.equals(logOperation)) {
		return logStore.updateGlobalTransactionDO(SessionConverter.convertGlobalTransactionDO(session));
	} else if (LogOperation.GLOBAL_REMOVE.equals(logOperation)) {
		return logStore.deleteGlobalTransactionDO(SessionConverter.convertGlobalTransactionDO(session));
	} else if (LogOperation.BRANCH_ADD.equals(logOperation)) {
		return logStore.insertBranchTransactionDO(SessionConverter.convertBranchTransactionDO(session));
	} else if (LogOperation.BRANCH_UPDATE.equals(logOperation)) {
		return logStore.updateBranchTransactionDO(SessionConverter.convertBranchTransactionDO(session));
	} else if (LogOperation.BRANCH_REMOVE.equals(logOperation)) {
		return logStore.deleteBranchTransactionDO(SessionConverter.convertBranchTransactionDO(session));
	} else {
		throw new StoreException("Unknown LogOperation:" + logOperation.name());
	}
}

LogStoreDataBaseDAO的insertGlobalTransactionDO方法:

@Override
public boolean insertGlobalTransactionDO(GlobalTransactionDO globalTransactionDO) {
	String sql = LogStoreSqlsFactory.getLogStoreSqls(dbType).getInsertGlobalTransactionSQL(globalTable);
	Connection conn = null;
	PreparedStatement ps = null;
	try {
		int index = 1;
		conn = logStoreDataSource.getConnection();
		conn.setAutoCommit(true);
		ps = conn.prepareStatement(sql);
		ps.setString(index++, globalTransactionDO.getXid());
		ps.setLong(index++, globalTransactionDO.getTransactionId());
		ps.setInt(index++, globalTransactionDO.getStatus());
		ps.setString(index++, globalTransactionDO.getApplicationId());
		ps.setString(index++, globalTransactionDO.getTransactionServiceGroup());
		String transactionName = globalTransactionDO.getTransactionName();
		transactionName = transactionName.length() > transactionNameColumnSize ?
			transactionName.substring(0, transactionNameColumnSize) :
			transactionName;
		ps.setString(index++, transactionName);
		ps.setInt(index++, globalTransactionDO.getTimeout());
		ps.setLong(index++, globalTransactionDO.getBeginTime());
		ps.setString(index++, globalTransactionDO.getApplicationData());
		return ps.executeUpdate() > 0;
	} catch (SQLException e) {
		throw new StoreException(e);
	} finally {
		IOUtil.close(ps, conn);
	}
}

到此我们的全局事务就开启完了。

2、执行业务代码 business.execute()

下面到了执行执行我们客户端业务代码了,rs = business.execute()方法;
然后遇到的db操作,这个时候我们的 DataSourceProxy进行处理。
DataSourceProxy的getConnection()方法:

@Override
public ConnectionProxy getConnection() throws SQLException {
	Connection targetConnection = targetDataSource.getConnection();
	return new ConnectionProxy(this, targetConnection);
}

ConnectionProxy的父类的方法:

@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
    //我们业务的数据库类型,mysql ,oracle...
	String dbType = getDbType();
	// support oracle 10.2+
	PreparedStatement targetPreparedStatement = null;
	//AT模式
	if (BranchType.AT == RootContext.getBranchType()) {
	    //sql识别器
		List<SQLRecognizer> sqlRecognizers = SQLVisitorFactory.get(sql, dbType);
		if (sqlRecognizers != null && sqlRecognizers.size() == 1) {
			SQLRecognizer sqlRecognizer = sqlRecognizers.get(0);
			if (sqlRecognizer != null && sqlRecognizer.getSQLType() == SQLType.INSERT) {
				TableMeta tableMeta = TableMetaCacheFactory.getTableMetaCache(dbType).getTableMeta(getTargetConnection(),
						sqlRecognizer.getTableName(), getDataSourceProxy().getResourceId());
				String[] pkNameArray = new String[tableMeta.getPrimaryKeyOnlyName().size()];
				tableMeta.getPrimaryKeyOnlyName().toArray(pkNameArray);
				targetPreparedStatement = getTargetConnection().prepareStatement(sql,pkNameArray);
			}
		}
	}
	if (targetPreparedStatement == null) {
		targetPreparedStatement = getTargetConnection().prepareStatement(sql);
	}
	//创建PreparedStatementProxy
	return new PreparedStatementProxy(this, targetPreparedStatement, sql);
}

下面会调用PreparedStatementProxy的execute方法:

public static <T, S extends Statement> T execute(List<SQLRecognizer> sqlRecognizers,
                                                     StatementProxy<S> statementProxy,
                                                     StatementCallback<T, S> statementCallback,
                                                    Object... args) throws SQLException {
	//不是AT模式
	if (!RootContext.requireGlobalLock() && BranchType.AT != RootContext.getBranchType()) {
		// Just work as original statement
		return statementCallback.execute(statementProxy.getTargetStatement(), args);
	}

	String dbType = statementProxy.getConnectionProxy().getDbType();
	if (CollectionUtils.isEmpty(sqlRecognizers)) {
		sqlRecognizers = SQLVisitorFactory.get(
				statementProxy.getTargetSQL(),
				dbType);
	}
	Executor<T> executor;
	if (CollectionUtils.isEmpty(sqlRecognizers)) {
		executor = new PlainExecutor<>(statementProxy, statementCallback);
	} else {
		if (sqlRecognizers.size() == 1) {
			SQLRecognizer sqlRecognizer = sqlRecognizers.get(0);
			//根据sql的类型找Executor
			switch (sqlRecognizer.getSQLType()) {
				case INSERT:  //spi加载InsertExecutor
					executor = EnhancedServiceLoader.load(InsertExecutor.class, dbType,
							new Class[]{StatementProxy.class, StatementCallback.class, SQLRecognizer.class},
							new Object[]{statementProxy, statementCallback, sqlRecognizer});
					break;
				case UPDATE:
					executor = new UpdateExecutor<>(statementProxy, statementCallback, sqlRecognizer);
					break;
				case DELETE:
					executor = new DeleteExecutor<>(statementProxy, statementCallback, sqlRecognizer);
					break;
				case SELECT_FOR_UPDATE:
					executor = new SelectForUpdateExecutor<>(statementProxy, statementCallback, sqlRecognizer);
					break;
				default:
					executor = new PlainExecutor<>(statementProxy, statementCallback);
					break;
			}
		} else {
			executor = new MultiExecutor<>(statementProxy, statementCallback, sqlRecognizers);
		}
	}
	T rs;
	try {
		//Executor执行
		rs = executor.execute(args);
	} catch (Throwable ex) {
		if (!(ex instanceof SQLException)) {
			// Turn other exception into SQLException
			ex = new SQLException(ex);
		}
		throw (SQLException) ex;
	}
	return rs;
}

我们以 insert为例看下吧:MySQLInsertExecutor的父类(BaseInsertExecutor)的父类(AbstractDMLBaseExecutor)的父类(BaseTransactionalExecutor)

BaseTransactionalExecutor的execute方法:

@Override
public T execute(Object... args) throws Throwable {
    //全局事务ID
	String xid = RootContext.getXID();
	if (xid != null) {
	    //绑定xid
		statementProxy.getConnectionProxy().bind(xid);
	}

	statementProxy.getConnectionProxy().setGlobalLockRequire(RootContext.requireGlobalLock());
	//执行
	return doExecute(args);
}

AbstractDMLBaseExecutor的doExecute方法:

@Override
public T doExecute(Object... args) throws Throwable {
	AbstractConnectionProxy connectionProxy = statementProxy.getConnectionProxy();
	if (connectionProxy.getAutoCommit()) {
		//执行自动提交的
		return executeAutoCommitTrue(args);
	} else {
		return executeAutoCommitFalse(args);
	}
}

executeAutoCommitTrue方法:

protected T executeAutoCommitTrue(Object[] args) throws Throwable {
	ConnectionProxy connectionProxy = statementProxy.getConnectionProxy();
	try {
	    //关闭自动提交,设置手动提交
		connectionProxy.setAutoCommit(false);
		return new LockRetryPolicy(connectionProxy).execute(() -> {
		    // 1、执行手动提交
			T result = executeAutoCommitFalse(args);
			//2、提交本地事务
			connectionProxy.commit();
			return result;
		});
	} catch (Exception e) {
		// when exception occur in finally,this exception will lost, so just print it here
		LOGGER.error("execute executeAutoCommitTrue error:{}", e.getMessage(), e);
		if (!LockRetryPolicy.isLockRetryPolicyBranchRollbackOnConflict()) {
			connectionProxy.getTargetConnection().rollback();
		}
		throw e;
	} finally {
		connectionProxy.getContext().reset();
		connectionProxy.setAutoCommit(true);
	}
}

executeAutoCommitFalse方法是核心,生成前置镜像,执行sql,没有提交本地事务,生成后置镜像,准备UndoLog数据

protected T executeAutoCommitFalse(Object[] args) throws Exception {
	if (!JdbcConstants.MYSQL.equalsIgnoreCase(getDbType()) && isMultiPk()) {
		throw new NotSupportYetException("multi pk only support mysql!");
	}
	//生成前置镜像
	TableRecords beforeImage = beforeImage();
	//执行sql,没有提交本地事务
	T result = statementCallback.execute(statementProxy.getTargetStatement(), args);
	//生成后置镜像
	TableRecords afterImage = afterImage(beforeImage);
	//准备UndoLog数据
	prepareUndoLog(beforeImage, afterImage);
	return result;
}

到了提交方法

@Override
public void commit() throws SQLException {
	try {
		LOCK_RETRY_POLICY.execute(() -> {
		    //提交
			doCommit();
			return null;
		});
	} catch (SQLException e) {
		if (targetConnection != null && !getAutoCommit()) {
			rollback();
		}
		throw e;
	} catch (Exception e) {
		throw new SQLException(e);
	}
}

doCommit()方法:

private void doCommit() throws SQLException {
	if (context.inGlobalTransaction()) {
	    //处在全局事务中,处理全局事务
		processGlobalTransactionCommit();
	} else if (context.isGlobalLockRequire()) {
		processLocalCommitWithGlobalLocks();
	} else {
		targetConnection.commit();
	}
}

processGlobalTransactionCommit方法也是核心,注册分支事务,插入undo log,本地事务提交

private void processGlobalTransactionCommit() throws SQLException {
	try {
	    //注册分支事务
		register();
	} catch (TransactionException e) {
		recognizeLockKeyConflictException(e, context.buildLockKeys());
	}
	try {
	    //插入undo log
		UndoLogManagerFactory.getUndoLogManager(this.getDbType()).flushUndoLogs(this);
		//本地事务提交
		targetConnection.commit();
	} catch (Throwable ex) {
		LOGGER.error("process connectionProxy commit error: {}", ex.getMessage(), ex);
		//RM异常要上报
		report(false);
		throw new SQLException(ex);
	}
	//开启上报,RM要上报完成
	if (IS_REPORT_SUCCESS_ENABLE) {
		report(true);
	}
	context.reset();
}

register()方法注册分支事务

private void register() throws TransactionException {
	if (!context.hasUndoLog() || context.getLockKeysBuffer().isEmpty()) {
		return;
	}
	//注册分支事务
	Long branchId = DefaultResourceManager.get().branchRegister(BranchType.AT, getDataSourceProxy().getResourceId(),
		null, context.getXid(), null, context.buildLockKeys());
	context.setBranchId(branchId);
}

我们再看下seata服务端的处理代码,处理注册分支事务:

DefaultCoordinator的doBranchRegister方法:

@Override
protected void doBranchRegister(BranchRegisterRequest request, BranchRegisterResponse response,
								RpcContext rpcContext) throws TransactionException {
	MDC.put(RootContext.MDC_KEY_XID, request.getXid());
	response.setBranchId(
			core.branchRegister(request.getBranchType(), request.getResourceId(), rpcContext.getClientId(),
					request.getXid(), request.getApplicationData(), request.getLockKey()));
}

DefaultCore的branchRegister方法:

public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid,
						   String applicationData, String lockKeys) throws TransactionException {
	return getCore(branchType).branchRegister(branchType, resourceId, clientId, xid,
		applicationData, lockKeys);
}

AbstractCore的branchRegister方法:

@Override
public Long branchRegister(BranchType branchType, String resourceId, String clientId, String xid,
						   String applicationData, String lockKeys) throws TransactionException {
	GlobalSession globalSession = assertGlobalSessionNotNull(xid, false);
	//锁住和执行,最终会调用表达式里的 GlobalSession.LockCallable函数接口。
	return SessionHolder.lockAndExecute(globalSession, () -> {
		globalSessionStatusCheck(globalSession);
		globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
		//组装分支事务信息
		BranchSession branchSession = SessionHelper.newBranchByGlobal(globalSession, branchType, resourceId,
				applicationData, lockKeys, clientId);
		MDC.put(RootContext.MDC_KEY_BRANCH_ID, String.valueOf(branchSession.getBranchId()));
		branchSessionLock(globalSession, branchSession);
		try {
		    //添加分支事务
			globalSession.addBranch(branchSession);
		} catch (RuntimeException ex) {
			branchSessionUnlock(branchSession);
			throw new BranchTransactionException(FailedToAddBranch, String
					.format("Failed to store branch xid = %s branchId = %s", globalSession.getXid(),
							branchSession.getBranchId()), ex);
		}
		if (LOGGER.isInfoEnabled()) {
			LOGGER.info("Register branch successfully, xid = {}, branchId = {}, resourceId = {} ,lockKeys = {}",
					globalSession.getXid(), branchSession.getBranchId(), resourceId, lockKeys);
		}
		return branchSession.getBranchId();
	});
}

GlobalSession的addBranch方法:

@Override
public void addBranch(BranchSession branchSession) throws TransactionException {
	for (SessionLifecycleListener lifecycleListener : lifecycleListeners) {
	    //写入分支事务
		lifecycleListener.onAddBranch(this, branchSession);
	}
	branchSession.setStatus(BranchStatus.Registered);
	add(branchSession);
}

到此注册完了分支任务。

3、全局事务提交 commitTransaction

加入所有的分支任务都完成,就到了我们的全局事务提交啦。
TransactionalTemplate的commitTransaction方法:

private void commitTransaction(GlobalTransaction tx) throws TransactionalExecutor.ExecutionException {
	try {
		triggerBeforeCommit();
		//核心
		tx.commit();
		triggerAfterCommit();
	} catch (TransactionException txe) {
		// 4.1 Failed to commit
		throw new TransactionalExecutor.ExecutionException(tx, txe,
			TransactionalExecutor.Code.CommitFailure);
	}
}

tx.commit()方法提交全局事务

@Override
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 <= 0 ? DEFAULT_TM_COMMIT_RETRY_COUNT : COMMIT_RETRY_COUNT;
	try {
		while (retry > 0) {
			try {
				//提交全局事务
				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 (xid.equals(RootContext.getXID())) {
			suspend();
		}
	}
	if (LOGGER.isInfoEnabled()) {
		LOGGER.info("[{}] commit status: {}", xid, status);
	}
}

DefaultTransactionManager的commit方法:


@Override
public GlobalStatus commit(String xid) throws TransactionException {
	GlobalCommitRequest globalCommit = new GlobalCommitRequest();
	globalCommit.setXid(xid);
	//TM发起netty请求,提交全局事务
	GlobalCommitResponse response = (GlobalCommitResponse) syncCall(globalCommit);
	return response.getGlobalStatus();
}

在seata服务端,TC的doGlobalCommit方法处理全局事务提交

@Override
protected void doGlobalCommit(GlobalCommitRequest request, GlobalCommitResponse response, RpcContext rpcContext)
		throws TransactionException {
	MDC.put(RootContext.MDC_KEY_XID, request.getXid());
	response.setGlobalStatus(core.commit(request.getXid()));
}

DeaultCore的commit方法,异步提交。

@Override
public GlobalStatus commit(String xid) throws TransactionException {
	GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
	//全局事务session是空
	if (globalSession == null) {
		return GlobalStatus.Finished;
	}
	globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
	// just lock changeStatus
	//加锁和执行
	boolean shouldCommit = SessionHolder.lockAndExecute(globalSession, () -> {
		if (globalSession.getStatus() == GlobalStatus.Begin) {
			// 关闭globalSession,有AT分支,释放全局锁
			globalSession.closeAndClean();
			//分支能否异步提交(分支事务是AT 或者 分支状态:BranchStatus.PhaseOne_Failed;)
			if (globalSession.canBeCommittedAsync()) {
			    //更改globalSession状态 :GlobalStatus.AsyncCommitting
				globalSession.asyncCommit();
				MetricsPublisher.postSessionDoneEvent(globalSession, GlobalStatus.Committed, false, false);
				return false;
			} else {
			    // 更改globalSession状态  :GlobalStatus.AsyncCommitting
				globalSession.changeGlobalStatus(GlobalStatus.Committing);
				return true;
			}
		}
		return false;
	});
	//是否应该提交,如果上边是支持异步的,都是不应该提交,也就是不会走下面提交的逻辑
	if (shouldCommit) {
	    //提交全局事务Session
		boolean success = doGlobalCommit(globalSession, false);
		//能异步的就异步提交
		if (success && globalSession.hasBranch() && globalSession.canBeCommittedAsync()) {
			globalSession.asyncCommit();
			return GlobalStatus.Committed;
		} else {
			return globalSession.getStatus();
		}
	} else {
	    //异步提交后,更改为GlobalStatus.Committed
		return globalSession.getStatus() == GlobalStatus.AsyncCommitting ? GlobalStatus.Committed : globalSession.getStatus();
	}
}

这个时候我们,TC有个定时任务处理异步提交

public void init() {
	retryRollbacking.scheduleAtFixedRate(
		() -> SessionHolder.distributedLockAndExecute(RETRY_ROLLBACKING, this::handleRetryRollbacking), 0,
		ROLLBACKING_RETRY_PERIOD, TimeUnit.MILLISECONDS);

	retryCommitting.scheduleAtFixedRate(
		() -> SessionHolder.distributedLockAndExecute(RETRY_COMMITTING, this::handleRetryCommitting), 0,
		COMMITTING_RETRY_PERIOD, TimeUnit.MILLISECONDS);
	//处理异步提交
	asyncCommitting.scheduleAtFixedRate(
		() -> SessionHolder.distributedLockAndExecute(ASYNC_COMMITTING, this::handleAsyncCommitting), 0,
		ASYNC_COMMITTING_RETRY_PERIOD, TimeUnit.MILLISECONDS);

	timeoutCheck.scheduleAtFixedRate(
		() -> SessionHolder.distributedLockAndExecute(TX_TIMEOUT_CHECK, this::timeoutCheck), 0,
		TIMEOUT_RETRY_PERIOD, TimeUnit.MILLISECONDS);

	undoLogDelete.scheduleAtFixedRate(
		() -> SessionHolder.distributedLockAndExecute(UNDOLOG_DELETE, this::undoLogDelete),
		UNDO_LOG_DELAY_DELETE_PERIOD, UNDO_LOG_DELETE_PERIOD, TimeUnit.MILLISECONDS);
}

handleAsyncCommitting方法:

protected void handleAsyncCommitting() {
    //找状态是:AsyncCommitting 的GlobalSession
	SessionCondition sessionCondition = new SessionCondition(GlobalStatus.AsyncCommitting);
	Collection<GlobalSession> asyncCommittingSessions =
			SessionHolder.getAsyncCommittingSessionManager().findGlobalSessions(sessionCondition);
	//没有就返回
	if (CollectionUtils.isEmpty(asyncCommittingSessions)) {
		return;
	}
	SessionHelper.forEach(asyncCommittingSessions, asyncCommittingSession -> {
		try {
			asyncCommittingSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
			//提交
			core.doGlobalCommit(asyncCommittingSession, true);
		} catch (TransactionException ex) {
			LOGGER.error("Failed to async committing [{}] {} {}", asyncCommittingSession.getXid(), ex.getCode(), ex.getMessage(), ex);
		}
	});
}

doGlobalCommit方法:

@Override
public boolean doGlobalCommit(GlobalSession globalSession, boolean retrying) throws TransactionException {
	boolean success = true;
	// start committing event
	MetricsPublisher.postSessionDoingEvent(globalSession, retrying);

	if (globalSession.isSaga()) {
	    //Saga
		success = getCore(BranchType.SAGA).doGlobalCommit(globalSession, retrying);
	} else {
		Boolean result = SessionHelper.forEach(globalSession.getSortedBranches(), branchSession -> {
			// 不是重试,跳过能异步提交的分支
			if (!retrying && branchSession.canBeCommittedAsync()) {
				return CONTINUE;
			}

			BranchStatus currentStatus = branchSession.getStatus();
			if (currentStatus == BranchStatus.PhaseOne_Failed) {
			    //分支状态失败,删除分支
				SessionHelper.removeBranch(globalSession, branchSession, !retrying);
				return CONTINUE;
			}
			try {
			    //分支事务提交消息发送给我们的客户端RM
				BranchStatus branchStatus = getCore(branchSession.getBranchType()).branchCommit(globalSession, branchSession);
				if (isXaerNotaTimeout(globalSession,branchStatus)) {
					LOGGER.info("Commit branch XAER_NOTA retry timeout, xid = {} branchId = {}", globalSession.getXid(), branchSession.getBranchId());
					branchStatus = BranchStatus.PhaseTwo_Committed;
				}
				switch (branchStatus) {
				    //分支事务二阶段提交,删除分支
					case PhaseTwo_Committed:
						SessionHelper.removeBranch(globalSession, branchSession, !retrying);
						return CONTINUE;
					case PhaseTwo_CommitFailed_Unretryable:
						//not at branch
						SessionHelper.endCommitFailed(globalSession, retrying);
						LOGGER.error("Committing global transaction[{}] finally failed, caused by branch transaction[{}] commit failed.", globalSession.getXid(), branchSession.getBranchId());
						return false;

					default:
						if (!retrying) {
							globalSession.queueToRetryCommit();
							return false;
						}
						if (globalSession.canBeCommittedAsync()) {
							LOGGER.error("Committing branch transaction[{}], status:{} and will retry later",
								branchSession.getBranchId(), branchStatus);
							return CONTINUE;
						} else {
							LOGGER.error(
								"Committing global transaction[{}] failed, caused by branch transaction[{}] commit failed, will retry later.", globalSession.getXid(), branchSession.getBranchId());
							return false;
						}
				}
			} catch (Exception ex) {
				StackTraceLogger.error(LOGGER, ex, "Committing branch transaction exception: {}",
					new String[] {branchSession.toString()});
				if (!retrying) {
					globalSession.queueToRetryCommit();
					throw new TransactionException(ex);
				}
			}
			return CONTINUE;
		});
		// Return if the result is not null
		if (result != null) {
			return result;
		}
		//如果有分支事务不能异步提交,返回false
		if (globalSession.hasBranch() && !globalSession.canBeCommittedAsync()) {
			LOGGER.info("Committing global transaction is NOT done, xid = {}.", globalSession.getXid());
			return false;
		}
		if (!retrying) {
			//contains not AT branch
			globalSession.setStatus(GlobalStatus.Committed);
		}
	}
	// if it succeeds and there is no branch, retrying=true is the asynchronous state when retrying. EndCommitted is
	// executed to improve concurrency performance, and the global transaction ends..
	//结束提交,删除全局事务信息
	if (success && globalSession.getBranchSessions().isEmpty()) {
		SessionHelper.endCommitted(globalSession, retrying);
		LOGGER.info("Committing global transaction is successfully done, xid = {}.", globalSession.getXid());
	}
	return success;
}

seata端上面分支事务提交后,seata会RPC回调我们的客户端。

AsyncWorker是DataSourceManager的init()方法初始化的。

@Override
public void init() {
	AsyncWorker asyncWorker = new AsyncWorker();
	asyncWorker.init();
	initAsyncWorker(asyncWorker);
}

AsyncWorker的init()方法:

public synchronized void init() {
	LOGGER.info("Async Commit Buffer Limit: {}", ASYNC_COMMIT_BUFFER_LIMIT);
	ScheduledExecutorService timerExecutor = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("AsyncWorker", 1, true));
	timerExecutor.scheduleAtFixedRate(() -> {
		try {
			//处理分支事务提交的回调
			doBranchCommits();

		} catch (Throwable e) {
			LOGGER.info("Failed at async committing ... {}", e.getMessage());

		}
	}, 10, 1000 * 1, TimeUnit.MILLISECONDS);
}

doBranchCommits()方法:

private void doBranchCommits() {
        ...
		try {
			//核心就是删除本地的UndoLog
			UndoLogManagerFactory.getUndoLogManager(dataSourceProxy.getDbType()).batchDeleteUndoLog(xids,
				branchIds, conn);
		} catch (Exception ex) {
			LOGGER.warn("Failed to batch delete undo log [" + branchIds + "/" + xids + "]", ex);
		}
		....
}

到此全局事务提交也已经结束了。

4、全局事务回滚 completeTransactionAfterThrowing

最后看下事务异常回滚:completeTransactionAfterThrowing

private void completeTransactionAfterThrowing(TransactionInfo txInfo, GlobalTransaction tx, Throwable originalException) throws TransactionalExecutor.ExecutionException {
	//roll back
	if (txInfo != null && txInfo.rollbackOn(originalException)) {
		try {
		    //回滚
			rollbackTransaction(tx, originalException);
		} catch (TransactionException txe) {
			// Failed to rollback
			throw new TransactionalExecutor.ExecutionException(tx, txe,
					TransactionalExecutor.Code.RollbackFailure, originalException);
		}
	} else {
		// not roll back on this exception, so commit
		commitTransaction(tx);
	}
}

rollbackTransaction方法:

private void rollbackTransaction(GlobalTransaction tx, Throwable originalException) throws TransactionException, TransactionalExecutor.ExecutionException {
	triggerBeforeRollback();
	//核心回滚
	tx.rollback();
	triggerAfterRollback();
	// 3.1 Successfully rolled back
	throw new TransactionalExecutor.ExecutionException(tx, GlobalStatus.RollbackRetrying.equals(tx.getLocalStatus())
		? TransactionalExecutor.Code.RollbackRetrying : TransactionalExecutor.Code.RollbackDone, originalException);
}
@Override
public void rollback() throws TransactionException {
    //参与者直接返回
	if (role == GlobalTransactionRole.Participant) {
		// Participant has no responsibility of rollback
		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("Ignore Rollback(): just involved in global transaction [{}]", xid);
		}
		return;
	}
	assertXIDNotNull();

	int retry = ROLLBACK_RETRY_COUNT <= 0 ? DEFAULT_TM_ROLLBACK_RETRY_COUNT : ROLLBACK_RETRY_COUNT;
	try {
		while (retry > 0) {
			try {
			    //Rpc调用seata回滚全局事务
				status = transactionManager.rollback(xid);
				break;
			} catch (Throwable ex) {
				LOGGER.error("Failed to report global rollback [{}],Retry Countdown: {}, reason: {}", this.getXid(), retry, ex.getMessage());
				retry--;
				if (retry == 0) {
					throw new TransactionException("Failed to report global rollback", ex);
				}
			}
		}
	} finally {
		if (xid.equals(RootContext.getXID())) {
			suspend();
		}
	}
	if (LOGGER.isInfoEnabled()) {
		LOGGER.info("[{}] rollback status: {}", xid, status);
	}
}

@Override
public GlobalStatus rollback(String xid) throws TransactionException {
	GlobalRollbackRequest globalRollback = new GlobalRollbackRequest();
	globalRollback.setXid(xid);
	//rpc调用seata全局事务回滚
	GlobalRollbackResponse response = (GlobalRollbackResponse) syncCall(globalRollback);
	return response.getGlobalStatus();
}

看下seata服务端,TC的doGlobalRollback方法

@Override
protected void doGlobalRollback(GlobalRollbackRequest request, GlobalRollbackResponse response,
								RpcContext rpcContext) throws TransactionException {
	MDC.put(RootContext.MDC_KEY_XID, request.getXid());
	response.setGlobalStatus(core.rollback(request.getXid()));
}

DefaultCore的rollback方法:

@Override
public GlobalStatus rollback(String xid) throws TransactionException {
	GlobalSession globalSession = SessionHolder.findGlobalSession(xid);
	if (globalSession == null) {
		return GlobalStatus.Finished;
	}
	globalSession.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
	// just lock changeStatus
	boolean shouldRollBack = SessionHolder.lockAndExecute(globalSession, () -> {
		globalSession.close(); // Highlight: Firstly, close the session, then no more branch can be registered.
		if (globalSession.getStatus() == GlobalStatus.Begin) {
		    //更新状态为Rollbacking
			globalSession.changeGlobalStatus(GlobalStatus.Rollbacking);
			return true;
		}
		return false;
	});
	if (!shouldRollBack) {
		return globalSession.getStatus();
	}
	//回滚
	boolean rollbackSuccess = doGlobalRollback(globalSession, false);
	return rollbackSuccess ? GlobalStatus.Rollbacked : globalSession.getStatus();
}

doGlobalRollback方法:

@Override
public boolean doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException {
	boolean success = true;
	// start rollback event
	MetricsPublisher.postSessionDoingEvent(globalSession, retrying);

	if (globalSession.isSaga()) {
		success = getCore(BranchType.SAGA).doGlobalRollback(globalSession, retrying);
	} else {
		Boolean result = SessionHelper.forEach(globalSession.getReverseSortedBranches(), branchSession -> {
			BranchStatus currentBranchStatus = branchSession.getStatus();
			if (currentBranchStatus == BranchStatus.PhaseOne_Failed) {
			    //删除分支事务
				SessionHelper.removeBranch(globalSession, branchSession, !retrying);
				return CONTINUE;
			}
			try {
			    //rpc 调用分支事务客户端的RM
				BranchStatus branchStatus = branchRollback(globalSession, branchSession);
				if (isXaerNotaTimeout(globalSession, branchStatus)) {
					LOGGER.info("Rollback branch XAER_NOTA retry timeout, xid = {} branchId = {}", globalSession.getXid(), branchSession.getBranchId());
					branchStatus = BranchStatus.PhaseTwo_Rollbacked;
				}
				switch (branchStatus) {
					case PhaseTwo_Rollbacked:
					    //删除分支事务
						SessionHelper.removeBranch(globalSession, branchSession, !retrying);
						LOGGER.info("Rollback branch transaction successfully, xid = {} branchId = {}", globalSession.getXid(), branchSession.getBranchId());
						return CONTINUE;
					case PhaseTwo_RollbackFailed_Unretryable:
						SessionHelper.endRollbackFailed(globalSession, retrying);
						LOGGER.info("Rollback branch transaction fail and stop retry, xid = {} branchId = {}", globalSession.getXid(), branchSession.getBranchId());
						return false;
					default:
						LOGGER.info("Rollback branch transaction fail and will retry, xid = {} branchId = {}", globalSession.getXid(), branchSession.getBranchId());
						if (!retrying) {
							globalSession.queueToRetryRollback();
						}
						return false;
				}
			} catch (Exception ex) {
				StackTraceLogger.error(LOGGER, ex,
					"Rollback branch transaction exception, xid = {} branchId = {} exception = {}",
					new String[] {globalSession.getXid(), String.valueOf(branchSession.getBranchId()), ex.getMessage()});
				if (!retrying) {
					globalSession.queueToRetryRollback();
				}
				throw new TransactionException(ex);
			}
		});
		// Return if the result is not null
		if (result != null) {
			return result;
		}
	}

	// In db mode, lock and branch data residual problems may occur.
	// Therefore, execution needs to be delayed here and cannot be executed synchronously.
	if (success) {
	    //结束回滚
		SessionHelper.endRollbacked(globalSession, retrying);
		LOGGER.info("Rollback global transaction successfully, xid = {}.", globalSession.getXid());
	}
	return success;
}

branchRollback方法:

@Override
public BranchStatus branchRollback(GlobalSession globalSession, BranchSession branchSession) throws TransactionException {
	return getCore(branchSession.getBranchType()).branchRollback(globalSession, branchSession);
}

AbstractCore的branchRollback方法:

@Override
public BranchStatus branchRollback(GlobalSession globalSession, BranchSession branchSession) throws TransactionException {
	try {
		BranchRollbackRequest request = new BranchRollbackRequest();
		request.setXid(branchSession.getXid());
		request.setBranchId(branchSession.getBranchId());
		request.setResourceId(branchSession.getResourceId());
		request.setApplicationData(branchSession.getApplicationData());
		request.setBranchType(branchSession.getBranchType());
		return branchRollbackSend(request, globalSession, branchSession);
	} catch (IOException | TimeoutException e) {
		throw new BranchTransactionException(FailedToSendBranchRollbackRequest,
				String.format("Send branch rollback failed, xid = %s branchId = %s",
						branchSession.getXid(), branchSession.getBranchId()), e);
	}
}

branchCommitSend方法:


protected BranchStatus branchCommitSend(BranchCommitRequest request, GlobalSession globalSession,
										BranchSession branchSession) throws IOException, TimeoutException {
	BranchCommitResponse response = (BranchCommitResponse) remotingServer.sendSyncRequest(
			branchSession.getResourceId(), branchSession.getClientId(), request);
	return response.getBranchStatus();
}

在我们的客户端,AbstractRMHandler的handle处理BranchRollbackRequest

@Override
public BranchRollbackResponse handle(BranchRollbackRequest request) {
	BranchRollbackResponse response = new BranchRollbackResponse();
	exceptionHandleTemplate(new AbstractCallback<BranchRollbackRequest, BranchRollbackResponse>() {
		@Override
		public void execute(BranchRollbackRequest request, BranchRollbackResponse response)
			throws TransactionException {
			//分支回滚
			doBranchRollback(request, response);
		}
	}, request, response);
	return response;
}

doBranchRollback 方法:

protected void doBranchRollback(BranchRollbackRequest request, BranchRollbackResponse response)
	throws TransactionException {
	String xid = request.getXid();
	long branchId = request.getBranchId();
	String resourceId = request.getResourceId();
	String applicationData = request.getApplicationData();
	if (LOGGER.isInfoEnabled()) {
		LOGGER.info("Branch Rollbacking: " + xid + " " + branchId + " " + resourceId);
	}
	//回滚
	BranchStatus status = getResourceManager().branchRollback(request.getBranchType(), xid, branchId, resourceId,
		applicationData);
	response.setXid(xid);
	response.setBranchId(branchId);
	response.setBranchStatus(status);
	if (LOGGER.isInfoEnabled()) {
		LOGGER.info("Branch Rollbacked result: " + status);
	}
}

DataSourceManager的branchRollback方法:

public BranchStatus branchRollback(BranchType branchType, String xid, long branchId, String resourceId,
								   String applicationData) throws TransactionException {
	DataSourceProxy dataSourceProxy = get(resourceId);
	if (dataSourceProxy == null) {
		throw new ShouldNeverHappenException();
	}
	try {
	    //调用UndoLog的undo方法,回滚数据
		UndoLogManagerFactory.getUndoLogManager(dataSourceProxy.getDbType()).undo(dataSourceProxy, xid, branchId);
	} catch (TransactionException te) {
		StackTraceLogger.info(LOGGER, te,
			"branchRollback failed. branchType:[{}], xid:[{}], branchId:[{}], resourceId:[{}], applicationData:[{}]. reason:[{}]",
			new Object[]{branchType, xid, branchId, resourceId, applicationData, te.getMessage()});
		if (te.getCode() == TransactionExceptionCode.BranchRollbackFailed_Unretriable) {
			return BranchStatus.PhaseTwo_RollbackFailed_Unretryable;
		} else {
			return BranchStatus.PhaseTwo_RollbackFailed_Retryable;
		}
	}
	return BranchStatus.PhaseTwo_Rollbacked;

}

到此全局回滚的大致流程也结束啦。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值