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的状态迁移,这部分后面统一通过状态迁移实现。
目录
相关文章
|
15天前
|
人工智能 JSON 供应链
畅用7个月无影 JVS Claw |手把手教你把JVS改造成「科研与产业地理情报可视化大师」
LucianaiB分享零成本畅用JVS Claw教程(学生认证享7个月使用权),并开源GeoMind项目——将JVS改造为科研与产业地理情报可视化AI助手,支持飞书文档解析、地理编码与腾讯地图可视化,助力产业关系图谱构建。
23515 12
畅用7个月无影 JVS Claw |手把手教你把JVS改造成「科研与产业地理情报可视化大师」
|
3天前
|
Shell API 开发工具
Claude Code 快速上手指南(新手友好版)
AI编程工具卷疯啦!Claude Code凭借任务驱动+终端原生的特性,成了开发者的效率搭子。本文从安装、登录、切换国产模型到常用命令,手把手带新手快速上手,全程避坑,30分钟独立用起来。
1032 7
|
4天前
|
人工智能 BI 持续交付
Claude Code 深度适配 DeepSeek V4-Pro 实测:全场景通关与真实体验报告
在 AI 编程工具日趋主流的今天,Claude Code 凭借强大的任务执行、工具调用与工程化能力,成为开发者与自动化运维的核心效率工具。但随着原生模型账号稳定性问题频发,寻找一套兼容、稳定、能力在线的替代方案变得尤为重要。DeepSeek V4-Pro 作为新一代高性能大模型,提供了完整兼容 Claude 协议的 API 接口,只需简单配置即可无缝驱动 Claude Code,且在任务执行、工具调用、复杂流程处理上表现极为稳定。
1307 3
|
9天前
|
人工智能 缓存 Shell
Claude Code 全攻略:命令大全 + 实战工作流(完整版)
Claude Code 是一款运行在终端环境下的 AI 编码助手,能够直接在项目目录中理解代码结构、编辑文件、执行命令、执行开发计划,并支持持久化记忆、上下文压缩、后台任务、多模型切换等专业能力。对于日常开发、项目维护、快速重构、代码审查等场景,它可以大幅减少手动操作、提升编码效率。本文从常用命令、界面模式、核心指令、记忆机制、图片处理、进阶工作流等维度完整说明,帮助开发者快速上手并稳定使用。
2404 4
|
2天前
|
人工智能 JSON BI
DeepSeek V4-Pro 接入 Claude Code 完全实战:体验、测试与关键避坑指南
Claude Code 作为当前主流的 AI 编程辅助工具,凭借强大的代码理解、工程执行与自动化能力深受开发者喜爱,但原生模型的使用成本相对较高。为了在保持能力的同时进一步降低开销,不少开发者开始寻找兼容度高、价格更友好的替代模型。DeepSeek V4 系列的发布带来了新的选择,该系列包含 V4-Pro 与 V4-Flash 两款模型,并提供了与 Anthropic 完全兼容的 API 接口,理论上只需简单修改配置,即可让 Claude Code 无缝切换为 DeepSeek 引擎。
829 0
|
19天前
|
人工智能 缓存 BI
Claude Code + DeepSeek V4-Pro 真实评测:除了贵,没别的毛病
JeecgBoot AI专题研究 把 Claude Code 接入 DeepSeek V4Pro,跑完 Skills —— OA 审批、大屏、报表、部署 5 大实战场景后的真实体验 ![](https://oscimg.oschina.net/oscnet/up608d34aeb6bafc47f
5962 22
Claude Code + DeepSeek V4-Pro 真实评测:除了贵,没别的毛病
|
20天前
|
人工智能 JSON BI
DeepSeek V4 来了!超越 Claude Sonnet 4.5,赶紧对接 Claude Code 体验一把
JeecgBoot AI专题研究 把 Claude Code 接入 DeepSeek V4Pro 的真实体验与避坑记录 本文记录我将 Claude Code 对接 DeepSeek 最新模型(V4Pro)后的真实体验,测试了 Skills 自动化查询和积木报表 AI 建表两个场景——有惊喜,也踩
7173 18