news 2026/10/14 16:58:21

全局事务入口感知子事务方法-TCC

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
全局事务入口感知子事务方法-TCC

一、核心前提:两个注解的分工

注解定位核心作用执行时机
@GlobalTransactional全局事务入口标记 “主方法”,创建全局事务 XID,管控整体提交 / 回滚主方法执行前
@TwoPhaseBusinessActionTCC 子方法标记 “Try 方法”,绑定 Confirm/Cancel,声明为 TCC 分支子方法执行时(被主方法调用)

简单说:@GlobalTransactional是 “总指挥”,@TwoPhaseBusinessAction是 “小兵”—— 总指挥不会提前知道有哪些小兵,而是小兵执行时主动向总指挥 “报到”。

二、完整流程:从主方法执行到子方法绑定

步骤 1:拦截@GlobalTransactional,创建全局事务(主方法执行前)

Seata 通过GlobalTransactionalInterceptor拦截所有带@GlobalTransactional的主方法,核心逻辑:

java

运行

// GlobalTransactionalInterceptor.java public Object invoke(MethodInvocation invocation) throws Throwable { // 1. 检查是否有全局事务 XID(首次执行时为 null) String xid = RootContext.getXID(); if (xid == null) { // 2. 创建全局事务,生成唯一 XID(如:127.0.0.1:8091:123456) GlobalTransaction tx = GlobalTransactionContext.createNew(); // 3. 开启全局事务(更新 global_table 状态为 “开始”) tx.begin(/* 超时时间 */, /* 事务名称 */); // 4. 将 XID 绑定到当前线程(ThreadLocal) RootContext.bind(tx.getXid()); } try { // 5. 执行主方法(此时会调用所有带 @TwoPhaseBusinessAction 的子方法) return invocation.proceed(); } catch (Exception e) { // 6. 异常时回滚全局事务(触发 Cancel 方法) GlobalTransactionContext.getCurrent().rollback(); throw e; } finally { // 7. 无异常则提交全局事务(触发 Confirm 方法) if (RootContext.getXID() != null) { GlobalTransactionContext.getCurrent().commit(); RootContext.unbind(); // 清除线程绑定的 XID } } }

关键:此时仅创建了全局事务 XID 并绑定到当前线程,还不知道任何 TCC 子方法的存在。

步骤 2:拦截@TwoPhaseBusinessAction,注册分支事务(子方法执行时)

当主方法执行到带@TwoPhaseBusinessAction的子方法时,Seata 通过TccActionInterceptor拦截该子方法,核心逻辑:

java

运行

// TccActionInterceptor.java public Object invoke(MethodInvocation invocation) throws Throwable { // 1. 检查当前线程是否有全局事务 XID(主方法已绑定) String xid = RootContext.getXID(); if (xid == null) { // 无全局事务:直接执行方法(非 TCC 分支,仅普通方法) return invocation.proceed(); } // 2. 解析 @TwoPhaseBusinessAction 注解(绑定 Confirm/Cancel 方法) Method tryMethod = invocation.getMethod(); TwoPhaseBusinessAction tccAnnotation = tryMethod.getAnnotation(TwoPhaseBusinessAction.class); TccAction tccAction = TccActionParser.parse(tryMethod); // 解析出 Try/Confirm/Cancel 方法 // 3. 注册 TCC 分支事务(核心:将子方法关联到全局事务 XID) BranchRegistration branchReg = new BranchRegistration(); branchReg.setXid(xid); branchReg.setBranchType(BranchType.TCC); branchReg.setResourceId(/* TCC 方法唯一标识:类名+方法名 */); branchReg.setApplicationData(/* 序列化 TccAction 对象(含 Confirm/Cancel) */); // 调用 Seata Server 注册分支,返回分支 ID Long branchId = TccResourceManager.INSTANCE.branchRegister(branchReg); try { // 4. 执行 Try 方法(业务逻辑:如冻结金额、预留资源) Object result = invocation.proceed(); // 5. 标记分支事务“Try 阶段完成” TccResourceManager.INSTANCE.branchReport(xid, branchId, BranchStatus.PhaseOne_Done); return result; } catch (Exception e) { // 6. Try 失败:标记分支状态,后续全局事务会触发 Cancel TccResourceManager.INSTANCE.branchReport(xid, branchId, BranchStatus.PhaseOne_Failed); throw e; } }

核心关键:

  • 子方法执行时,通过ThreadLocal获取主方法绑定的 XID,确认自己属于哪个全局事务;
  • 解析@TwoPhaseBusinessAction注解,将 Try/Confirm/Cancel 方法序列化后,注册为 “TCC 分支事务”,并写入 Seata 数据库的branch_table(关联 XID);
  • 此时,全局事务(主方法)就通过branch_table知道了 “自己有哪些 TCC 子方法”。
步骤 3:全局事务提交 / 回滚,触发二阶段方法(主方法执行后)

当主方法执行完成(无异常 / 有异常),@GlobalTransactional触发提交 / 回滚逻辑,核心是从branch_table读取已注册的 TCC 分支:

java

运行

// DefaultGlobalTransaction.java public void commit() throws TransactionException { // 1. 根据 XID 查询所有已注册的 TCC 分支(来自步骤 2 的注册) List<BranchDO> branchList = branchStorage.findBranchListByXid(this.xid); for (BranchDO branch : branchList) { if (branch.getBranchType() == BranchType.TCC) { // 2. 反序列化 TccAction 对象(获取 Confirm 方法) TccAction tccAction = JSON.parseObject(branch.getApplicationData(), TccAction.class); // 3. 反射执行 Confirm 方法(子方法的二阶段) invokeTargetMethod(tccAction.getConfirmMethod(), branch.getArgs()); // 4. 更新分支状态为“已提交” branchStorage.updateBranchStatus(branch.getBranchId(), BranchStatus.PhaseTwo_Committed); } } // 5. 更新全局事务状态为“已提交” globalStorage.updateGlobalStatus(this.xid, GlobalStatus.Committed); }

回滚逻辑同理:从branch_table读取分支,执行Cancel方法。

三、核心原理总结(一句话说透)

@GlobalTransactional不会 “主动扫描” 子方法的@TwoPhaseBusinessAction,而是:

  1. 主方法执行前,创建全局事务 XID 并绑定到当前线程;
  2. 子方法执行时,Seata 拦截@TwoPhaseBusinessAction,通过线程绑定的 XID 向全局事务 “注册自己”;
  3. 全局事务提交 / 回滚时,从数据库读取已注册的 TCC 分支,执行二阶段方法。

四、关键细节(避免误解)

  1. 线程绑定是核心桥梁:XID 存储在RootContext(本质是ThreadLocal<String>),子方法和主方法在同一个线程执行,因此能拿到同一个 XID,这是 “关联” 的基础。
  2. 非侵入式拦截:无需在主方法中显式声明子方法,只要子方法加@TwoPhaseBusinessAction且被主方法调用,就会自动注册为分支 —— 这是 Seata TCC 无侵入的关键。
  3. 分支注册是持久化保障:TCC 分支信息写入branch_table,即使 Seata Server 宕机,恢复后仍能根据 XID 找到分支方法,保证二阶段执行(幂等性由业务层保证)。

五、调试验证(快速确认绑定关系)

  1. 断点 1:GlobalTransactionalInterceptor.invoke()→ 查看 XID 的创建和绑定;
  2. 断点 2:TccActionInterceptor.invoke()→ 查看子方法如何解析@TwoPhaseBusinessAction并注册分支;
  3. 数据库验证:执行主方法后,查询branch_table:

    sql

    SELECT xid, resource_id, application_data FROM branch_table WHERE branch_type = 'TCC';
    application_data字段会序列化存储 Try/Confirm/Cancel 方法的全限定名,可直接看到主方法(XID)和子方法的绑定关系。

最终类比

  • @GlobalTransactional像 “项目经理”,启动项目(创建 XID)后开始干活;
  • @TwoPhaseBusinessAction像 “员工”,干活时(执行子方法)主动向项目经理报到(注册分支);
  • 项目收尾时(提交 / 回滚),项目经理根据报到记录(branch_table)安排员工做收尾工作(Confirm/Cancel)。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 4:48:39

Obsidian导入工具终极指南:5分钟实现多平台笔记无缝迁移

Obsidian导入工具终极指南&#xff1a;5分钟实现多平台笔记无缝迁移 【免费下载链接】obsidian-importer Obsidian Importer lets you import notes from other apps and file formats into your Obsidian vault. 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-impo…

作者头像 李华
网站建设 2026/10/14 18:39:52

9、Linux 用户与环境管理:安全与配置指南

Linux 用户与环境管理:安全与配置指南 1. 用户和组管理 在 Linux 系统中,用户和组管理至关重要。以下是一些关键要点: - root 用户安全 - 限制登录终端 :可通过 man securetty 查看相关信息,限制 root 从哪些终端控制台登录。 - 谨慎执行命令 :以 root 身份执…

作者头像 李华
网站建设 2026/10/11 0:52:34

Windows动态桌面完全指南:打造你的专属视觉盛宴

Windows动态桌面完全指南&#xff1a;打造你的专属视觉盛宴 【免费下载链接】DreamScene2 一个小而快并且功能强大的 Windows 动态桌面软件 项目地址: https://gitcode.com/gh_mirrors/dr/DreamScene2 厌倦了千篇一律的静态桌面背景&#xff1f;想要让你的Windows桌面&q…

作者头像 李华
网站建设 2026/10/15 1:31:35

15、Linux系统管理、监控与网络服务配置全解析

Linux系统管理、监控与网络服务配置全解析 1. 用户登录信息提取与安全分析 在系统管理中,提取用户登录信息是一项重要的工作。通过解析 lastlog 命令的输出,我们可以查找已知处于活动状态的单个账户信息。例如: hart 1 192.168.1.100 Sat Feb 26 10:08…

作者头像 李华
网站建设 2026/10/14 18:20:40

后台管理系统权限配置终极指南:从基础到企业级实战

后台管理系统权限配置终极指南&#xff1a;从基础到企业级实战 【免费下载链接】d2-admin 项目地址: https://gitcode.com/gh_mirrors/d2a/d2-admin 在现代化的后台管理系统开发中&#xff0c;权限管理是确保系统安全性和灵活性的核心环节。D2Admin作为一款优秀的中后台…

作者头像 李华
网站建设 2026/10/13 13:20:24

SQL代码美化工具使用指南:提升开发效率的终极解决方案

在数据库开发过程中&#xff0c;杂乱无章的SQL代码不仅影响阅读体验&#xff0c;更会显著降低团队协作效率。SQL Beautify作为一款专业的VS Code扩展工具&#xff0c;专门针对SQL和HQL代码格式化设计&#xff0c;能够将原本难以维护的查询语句瞬间变得清晰规范。 【免费下载链接…

作者头像 李华