尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Seata 核心实现剖析:AT 模式、全局锁、事务协调与 SPI 扩展

Seata 核心实现剖析:AT 模式、全局锁、事务协调与 SPI 扩展
📅 发布时间:2026/6/23 10:23:29

Seata 核心实现剖析:AT 模式、全局锁、事务协调与 SPI 扩展

一、整体架构与核心组件

Seata 的架构围绕三个核心角色展开,它们之间通过 Netty 通信,以 Seata Server(TC)为中心进行全局事务的协调。

  • TC(Transaction Coordinator):独立部署的 Seata Server,维护全局事务和分支事务的状态,驱动二阶段的提交或回滚。存储端支持数据库(global_table、branch_table、lock_table)或 Redis。
  • TM(Transaction Manager):嵌入在发起方微服务中,通过@GlobalTransactional注解声明全局事务边界,负责向 TC 开启、提交或回滚全局事务。
  • RM(Resource Manager):嵌入在每个参与方微服务中,管理分支事务的资源(如数据库连接),向 TC 注册分支事务,并响应 TC 的二阶段指令。

通信层使用 Netty 实现 TM/RM 与 TC 之间的 RPC 调用,序列化支持 kryo、protobuf 等。TC 是无状态的,事务上下文持久化在数据库中,因此 TC 可以集群部署,任意一个节点宕机后,其他节点可以从数据库恢复未完成的事务。

二、AT 模式的 SQL 拦截与 undo log 生成

AT 模式的无侵入性建立在DataSourceProxy和StatementProxy两层代理之上。

2.1 数据源代理链

在 Spring Boot 集成中,Seata 通过SeataAutoDataSourceProxyCreator自动将业务数据源包装为DataSourceProxy。当应用通过dataSource.getConnection()获取连接时,实际返回的是ConnectionProxy对象,其内部持有真实的物理连接。

ConnectionProxy重写了createStatement()和prepareStatement(),返回StatementProxy或PreparedStatementProxy,由此实现对 SQL 执行过程的全面拦截。

2.2 SQL 执行的核心流程

以PreparedStatementProxy.executeUpdate()为例,核心执行路径如下:

publicintexecuteUpdate(){// 1. 构建 SQL 识别器,解析 SQL 类型、表名、WHERE 条件等SQLRecognizerrecognizer=SQLVisitorFactory.get(targetSQL,dbType);// 2. 生成前置镜像:执行 SELECT ... FOR UPDATE 查询原始数据TableRecordsbeforeImage=executor.beforeImage(recognizer);// 3. 执行实际的业务 SQL(UPDATE/INSERT/DELETE)introws=targetStatement.executeUpdate();// 4. 生成后置镜像:查询变更后的数据TableRecordsafterImage=executor.afterImage(recognizer,beforeImage);// 5. 构建 undo log 并写入数据库undoLogManager.insertUndoLog(connectionProxy,beforeImage,afterImage);returnrows;}

生成前置镜像和后置镜像的前提是 SQL 必须有明确的 WHERE 条件,否则SQLRecognizer无法精确识别受影响的行,会抛出异常要求修改 SQL。

2.3 undo log 的结构

undo log 写入业务数据库的undo_log表,核心字段包括:

  • xid:全局事务 ID。
  • branch_id:分支事务 ID。
  • rollback_info:JSON 序列化的前后镜像数据,包含beforeImage和afterImage,以及表结构和行数据。
  • log_status:日志状态(NORMAL、GLOBAL_FINISHED等)。

回滚时,RM 从rollback_info中解析出beforeImage,反向生成 UPDATE 或 DELETE 语句执行。提交时,RM 将log_status置为GLOBAL_FINISHED,后续由后台任务异步清理。

三、全局锁与写隔离机制

AT 模式在一阶段就提交了本地事务,数据已持久化到数据库,必须通过全局锁防止其他全局事务在二阶段完成前修改同一行数据。

3.1 全局锁的申请与存储

在一阶段本地事务提交前,RM 通过ConnectionProxy.commit()触发全局锁申请。核心逻辑在LockManagerImpl中,它向 TC 发送GlobalLockRequest,TC 将锁记录写入lock_table:

lock_table: row_key = 表名:主键值 xid = 当前全局事务 ID branch_id = 当前分支事务 ID

如果同一行数据已被其他全局事务锁定,TC 返回锁冲突,RM 会进入自旋重试(默认 10 秒),超时后抛出LockConflictException,触发全局事务回滚。

3.2 全局锁的释放

  • 二阶段提交:TC 通知 RM 提交,RM 在异步删除 undo log 的同时,通知 TC 释放该分支持有的所有全局锁。
  • 二阶段回滚:RM 执行 undo log 的回滚 SQL,完成后释放全局锁。

3.3 读隔离

默认情况下,AT 模式的读操作不申请全局锁,读的是已提交数据(本地事务已提交,但全局事务可能尚未结束)。如果需要读已提交,可以在 SQL 中加SELECT ... FOR UPDATE,该语句会触发全局锁申请,如果数据被其他全局事务锁定,则等待或抛出异常。

四、事务协调器 TC 的内部机制

TC 是事务的中枢,负责全局事务的生命周期管理和分支事务的调度。

4.1 全局事务状态机

TC 内部通过DefaultCore处理 TM/RM 的请求。全局事务的状态流转如下:

Begin -> (TM) -> COMMITTING -> (所有分支成功) -> COMMITTED -> ROLLBACKING -> (任一分支失败) -> ROLLBACKED

状态存储在global_table中,事务恢复时根据状态判断应该走提交还是回滚路径。

4.2 二阶段异步提交

当 TM 发起全局提交时,TC 将全局事务状态置为COMMITTING,然后通过 Netty 向所有已注册的分支异步发送提交指令。由于 AT 模式一阶段已经提交了本地事务,二阶段提交只是删除 undo log 和释放全局锁,即使某个分支提交失败,TC 也会通过重试机制反复调用,直到成功或人工介入。全局事务状态变为COMMITTED后,TC 删除对应的global_table记录。

4.3 故障恢复与重试

TC 宕机重启后,会从global_table中查询所有状态非终态(COMMITTED/ROLLBACKED)的全局事务,根据其当前状态重新驱动二阶段。RM 侧也有RetryRollbackingTask和RetryCommittingTask定时检查未完成的分支事务,主动向 TC 查询全局状态。

五、TCC 模式的防悬挂与幂等

TCC 模式下,开发者自行实现try、confirm、cancel三个方法。Seata 通过TccActionInterceptor对这些方法进行增强,解决两个关键问题:防悬挂和幂等。

5.1 防悬挂

问题场景:网络延迟导致cancel先于try到达。如果不处理,cancel会被忽略,后续try执行后,资源没有对应的补偿操作。

Seata 的解决方式:在TccActionInterceptor中,当cancel方法调用时,检查branch_table中是否已存在该分支的记录。如果不存在(说明try还未执行),则先插入一条状态为PhaseTwo_Rollbacked的空分支记录。后续try到来时,检查到该记录,直接跳过执行。

5.2 幂等控制

Seata 通过branch_table中的xid和branch_id唯一标识一个 TCC 分支。try方法执行前,检查是否已有该分支记录,若有则判断状态:已try成功则幂等返回;已cancel或confirm则根据状态决定行为。开发者也可以通过业务表增加事务状态字段自行实现幂等。

六、SPI 扩展点体系

Seata 内部大量使用 SPI 机制,允许替换核心组件。SPI 加载器为EnhancedServiceLoader,支持按order排序、按别名加载、以及从META-INF/services/和META-INF/seata/目录扫描实现。

关键扩展点:

  • ConfigurationProvider:配置源,默认从registry.conf或 Spring Boot 配置中加载。
  • RegistryProvider:注册中心,支持 Nacos、Consul、Zookeeper、Redis 等。
  • StoreMode:存储模式,支持db(数据库)和redis。
  • TransactionManager/ResourceManager:事务管理器和资源管理器核心接口。
  • LoadBalance:TC 节点间的负载均衡策略,默认XID取模。
  • Serializer:序列化方式,默认 kryo。
  • LockStore:全局锁存储,默认使用数据库lock_table,可扩展为 Redis 实现以获得更好的锁性能。

这些扩展点使得 Seata 可以适配不同的注册中心、存储介质和序列化方案,同时允许在特殊场景下自定义事务管理器或锁管理器。

七、高性能设计要点

7.1 一阶段直接提交

AT 模式的一阶段直接提交本地事务,释放了数据库连接和行锁,避免了传统 2PC 的资源长期持有问题。全局事务的耗时主要取决于业务逻辑和远程调用,而非锁等待。

7.2 Netty 异步通信

TM/RM 与 TC 之间通过 Netty 进行异步通信,支持请求响应、心跳和重连。多路复用使得单连接能承载大量并发事务,TC 单节点可以支撑数万 TPS。

7.3 undo log 异步删除

二阶段提交时,RM 不会同步等待 undo log 删除完成,而是异步执行删除并释放全局锁。如果删除失败,后台重试机制会反复尝试,不影响全局事务的提交。

7.4 批量锁申请与释放

在高并发场景下,RM 可以将多行数据的全局锁合并为一次请求发送给 TC,减少 RPC 次数。同样,锁释放也支持批量操作。

八、总结

Seata 通过三层代理(DataSourceProxy、ConnectionProxy、StatementProxy)实现了对 SQL 的拦截与 undo log 的自动生成,使 AT 模式具备了零侵入的特性。全局锁在 TC 端通过lock_table管理,解决了一阶段提交后的写隔离问题。TC 的状态机驱动二阶段异步提交与故障恢复,保证了最终一致性。TCC 模式通过拦截器处理防悬挂和幂等,弥补了业务自行实现补偿的复杂度。SPI 扩展体系则让 Seata 能够灵活适配多种注册中心、存储方案和通信协议。

理解这些核心机制的源码实现,有助于在生产环境中进行针对性的性能调优和问题排查。

推荐阅读:

  • Seata 官方文档 - AT 模式
  • Seata Server 源码导读
  • Seata SPI 扩展指南

相关新闻

  • 【Spring Cloud 微服务】——第二章 服务注册与发现和远程调用
  • 中国汉堡加盟实操技术分享:模式、扶持与盈利逻辑拆解 - 起跑123
  • C++课后习题训练记录Day137

最新新闻

  • Manim物理模拟:别自己写欧拉了!
  • 古典密码 - 维吉尼亚密码破解
  • 每日一个开源项目(第138篇):OpenMontage - 把 AI 编程助手变成完整的视频制作团队
  • Childhood,23款童年卡牌游戏复刻
  • 从Copilot到Agent——我的开发工作流正在被颠覆的技术文章大纲
  • PortSwigger SQL注入LAB7 LAB8 LAB9

日新闻

  • Arduino-ESP32项目深度解析:解锁隐藏芯片支持与架构演进
  • 2026年 系统窗厂家/品牌推荐榜单:隔音系统窗+高端系统门窗的核心优势与选购指南 - 品牌发掘
  • NVBench:首个双语非言语发声语音合成评测基准详解与实践

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号