开篇
这篇文章的目的主要是讲解Fescar TC执行rollback的流程,目的是讲解清楚rollback流程中的一些步骤。
遗憾的是因为rollback本身涉及Fescar的分支事务注册上报,如果事先不了解Fescar的分支事务,有些逻辑理解起来会有一些奇怪,对于branchSession本身还未了解,所以只能单独讲解rollback流程。
背景
说明:
- 分支事务中数据的 本地锁 由本地事务管理,在分支事务 Phase1 结束时释放。
同时,随着本地事务结束,连接 也得以释放。 - 分支事务中数据的 全局锁 在事务协调器侧管理,在决议 Phase2 全局提交时,全局锁马上可以释放。只有在决议全局回滚的情况下,全局锁 才被持有至分支的 Phase2 结束。
这个设计,极大地减少了分支事务对资源(数据和连接)的锁定时间,给整体并发和吞吐的提升提供了基础。
这里需要重点指出的是:Phase1阶段的commit()操作是各个分支事务本地的事务操作。Phase2阶段的操作是全局的commit()和rollback()。TC-rollback流程指的就是Phase2阶段。
TC rollback流程介绍
rollback主流程
- 1.根据transactionId查找begin阶段生成的GlobalSession对象。
- 2.对GlobalSession对象进行close操作。
- 3.TC通知所有RM(各分支事务的资源管理器)进行全局回滚操作(doGlobalRollback)。
TC rollback源码分析
public class DefaultCore implements Core {
public GlobalStatus rollback(String xid) throws TransactionException {
// 查找全局GlobalSession对象
GlobalSession globalSession =
SessionHolder.findGlobalSession(XID.getTransactionId(xid));
if (globalSession == null) {
return GlobalStatus.Finished;
}
GlobalStatus status = globalSession.getStatus();
// Highlight: Firstly, close the session,
// then no more branch can be registered.
// 关闭全局的GlobalSession对象。
globalSession.close();
if (status == GlobalStatus.Begin) {
globalSession.changeStatus(GlobalStatus.Rollbacking);
// 执行全局的rollback操作
doGlobalRollback(globalSession, false);
}
return globalSession.getStatus();
}
}
说明:
- 查找全局的GlobalSession对象。
- 关闭GlobalSession对象。
- 执行全局的rollback操作。
GlobalSession关闭操作
public class GlobalSession implements SessionLifecycle, SessionStorable {
public void close() throws TransactionException {
if (active) {
for (SessionLifecycleListener lifecycleListener : lifecycleListeners) {
lifecycleListener.onClose(this);
}
}
}
public void onEnd(GlobalSession globalSession) throws TransactionException {
removeGlobalSession(globalSession);
}
public void onStatusChange(GlobalSession globalSession, GlobalStatus status) throws TransactionException {
updateGlobalSessionStatus(globalSession, status);
}
public void updateGlobalSessionStatus(GlobalSession session, GlobalStatus status) throws TransactionException {
transactionStoreManager.writeSession(LogOperation.GLOBAL_UPDATE, session);
}
public void changeStatus(GlobalStatus status) throws TransactionException {
for (SessionLifecycleListener lifecycleListener : lifecycleListeners) {
lifecycleListener.onStatusChange(this, status);
}
this.status = status;
}
}
- GlobalSession的close操作调用生命周期监听器lifecycleListener.onClose()。
- lifecycleListener指的是DefaultSessionManager对象。
DefaultSessionManager操作
public class SessionHolder {
public static GlobalSession findGlobalSession(Long transactionId)
throws TransactionException {
return getRootSessionManager().findGlobalSession(transactionId);
}
}
public class DefaultSessionManager extends AbstractSessionManager {}
public abstract class AbstractSessionManager implements
SessionManager, SessionLifecycleListener {
protected Map<Long, GlobalSession> sessionMap = new ConcurrentHashMap<>();
public GlobalSession findGlobalSession(Long transactionId)
throws TransactionException {
return sessionMap.get(transactionId);
}
public void onClose(GlobalSession globalSession) throws TransactionException {
globalSession.setActive(false);
}
public void removeGlobalSession(GlobalSession session)
throws TransactionException {
transactionStoreManager.writeSession(LogOperation.GLOBAL_REMOVE, session);
sessionMap.remove(session.getTransactionId());
}
}
说明:
- 生命周期监听器的onClose()设置GlobalSession对象的active状态为false。
- findGlobalSession()方法从DefaultSessionManager返回GlobalSession对象。
public class DefaultCore implements Core {
public void doGlobalRollback(GlobalSession globalSession, boolean retrying) throws TransactionException {
for (BranchSession branchSession : globalSession.getReverseSortedBranches()) {
BranchStatus currentBranchStatus = branchSession.getStatus();
if (currentBranchStatus == BranchStatus.PhaseOne_Failed) {
continue;
}
try {
BranchStatus branchStatus = resourceManagerInbound.branchRollback(XID.generateXID(branchSession.getTransactionId()), branchSession.getBranchId(),
branchSession.getResourceId(), branchSession.getApplicationData());
switch (branchStatus) {
case PhaseTwo_Rollbacked:
globalSession.removeBranch(branchSession);
LOGGER.error("Successfully rolled back branch " + branchSession);
continue;
case PhaseTwo_RollbackFailed_Unretryable:
changeToRollbackFailedStatus(globalSession);
globalSession.end();
LOGGER.error("Failed to rollback global[" + globalSession.getTransactionId() + "] since branch[" + branchSession.getBranchId() + "] rollback failed");
return;
default:
LOGGER.info("Failed to rollback branch " + branchSession);
if (!retrying) {
queueToRetryRollback(globalSession);
}
return;
}
} catch (Exception ex) {
LOGGER.info("Exception rollbacking branch " + branchSession, ex);
if (!retrying) {
queueToRetryRollback(globalSession);
if (ex instanceof TransactionException) {
throw (TransactionException) ex;
} else {
throw new TransactionException(ex);
}
}
}
}
if (globalSession.hasBranch()) {
changeToRollbackFailedStatus(globalSession);
} else {
changeToRollbackedStatus(globalSession);
}
globalSession.end();
}
}
说明:
- doGlobalRollback()遍历GlobalSession当中所有的branchSession执行回滚操作。
- 内部涉及到GlobalSession的状态迁移,这部分后面统一通过状态迁移实现。