Fescar TC-rollback流程-阿里云开发者社区

开发者社区> 晴天哥> 正文

Fescar TC-rollback流程

简介: 开篇  这篇文章的目的主要是讲解Fescar TC执行rollback的流程,目的是讲解清楚rollback流程中的一些步骤。  遗憾的是因为rollback本身涉及Fescar的分支事务注册上报,如果事先不了解Fescar的分支事务,有些逻辑理解起来会有一些奇怪,对于branchSession本身还未了解,所以只能单独讲解rollback流程。
+关注继续查看

开篇

 这篇文章的目的主要是讲解Fescar TC执行rollback的流程,目的是讲解清楚rollback流程中的一些步骤。

 遗憾的是因为rollback本身涉及Fescar的分支事务注册上报,如果事先不了解Fescar的分支事务,有些逻辑理解起来会有一些奇怪,对于branchSession本身还未了解,所以只能单独讲解rollback流程。


背景

Fescar事务管理
说明:

  • 分支事务中数据的 本地锁 由本地事务管理,在分支事务 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的状态迁移,这部分后面统一通过状态迁移实现。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Fescar example解析 - TM流程
背景  Fescar 是 阿里巴巴 开源的 分布式事务中间件,以 高效 并且对业务0侵入的方式,解决微服务场景下面临的分布式事务问题,介绍可以参考Fescar介绍。  Fescar example解析系列主要是通过阅读Fescar的example源码梳理Fescar的整体逻辑,偏重于整体流程的梳理,让大家在整体上能够有一个宏观了解。
3269 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
8381 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,大概有三种登录方式:
2750 0
Fescar - RM 提交本地事务流程
开篇  这篇文章的目的是介绍Fescar的提交流程(Commit)和回滚流程(Rollback),这两个流程其实是Fescar中RM的核心逻辑,涉及和TC交互的流程。  由于RM和TC交互涉及到网络通信,所以这块我们暂时只关注RM端的处理流程而暂时忽略网络通信的过程,网络通信的过程值得通过一篇文章单独进行描述。
1194 0
Fescar TC-rollback流程
开篇  这篇文章的目的主要是讲解Fescar TC执行rollback的流程,目的是讲解清楚rollback流程中的一些步骤。  遗憾的是因为rollback本身涉及Fescar的分支事务注册上报,如果事先不了解Fescar的分支事务,有些逻辑理解起来会有一些奇怪,对于branchSession本身还未了解,所以只能单独讲解rollback流程。
893 0
阿里云服务器ECS远程登录用户名密码查询方法
阿里云服务器ECS远程连接登录输入用户名和密码,阿里云没有默认密码,如果购买时没设置需要先重置实例密码,Windows用户名是administrator,Linux账号是root,阿小云来详细说下阿里云服务器远程登录连接用户名和密码查询方法
10805 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
12016 0
Fescar TC-beigin流程
开篇  这篇文章是用来讲解清楚TC(Transaction Coordinator:事务协调器)在处理TM发送过来的begin操作(事务开启操作)。  核心逻辑包括GlobalSession对象的生成、GlobalSession的持久化以及XID生成。
1000 0
Fescar TC-commit流程
开篇  这篇文章的目的主要是讲解Fescar TC执行commit的流程,目的是讲解清楚commit流程中的一些步骤。  遗憾的是因为commit本身Fescar的分支事务注册上报,如果事先不了解Fescar的分支事务,有些逻辑理解起来会有一些奇怪,对于branchSession本身还未了解,所以只能单独讲解commit流程。
863 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
6525 0
+关注
晴天哥
专注java技术,热爱长跑和阅读开源代码
400
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载