Seata 的三大核心组件:TC、TM、RM 的作用和交互流程
Seata 是一款开源的分布式事务解决方案,它的架构核心由三个重要的组件构成:TC、TM 和 RM。理解这三个组件的作用以及它们之间的交互流程,是掌握 Seata 分布式事务原理的关键。
以下是详细的解析:
一、 三大核心组件的作用
1. TC (Transaction Coordinator) - 事务协调者
- 角色定位:“总指挥”。它是 Seata 的 Server 端,是一个独立部署的服务(通常会做集群高可用)。
- 核心作用:
- 维护全局事务和分支事务的状态。
- 负责协调并驱动全局事务的提交(Global Commit)或回滚(Global Rollback)。
- 生成全局唯一的事务 ID(XID)。
2. TM (Transaction Manager) - 事务管理器
- 角色定位:“发起者 / 项目经理”。它是嵌入在微服务客户端(Client 端)的组件,通常存在于发起全局事务的那个微服务中(例如电商系统中的“订单服务”)。
- 核心作用:
- 定义全局事务的边界(即从哪里开始,到哪里结束)。
- 向 TC 申请开启一个全局事务。
- 根据业务代码的执行结果(成功或抛出异常),向 TC 发起全局提交或全局回滚的指令。
3. RM (Resource Manager) - 资源管理器
- 角色定位:“执行者 / 工人”。它也是嵌入在微服务客户端(Client 端)的组件,存在于每一个参与分布式事务的微服务中(例如“订单服务”、“库存服务”、“账户服务”)。
- 核心作用:
- 管理分支事务处理的资源(通常是本地数据库)。
- 向 TC 注册分支事务,并将其纳入 XID 对应的全局事务管辖中。
- 向 TC 汇报分支事务的执行状态。
- 接收 TC 的指令,驱动本地事务的提交或回滚(在 AT 模式下,依赖
undo_log表进行回滚)。
二、 组件之间的交互流程(以 AT 模式为例)
Seata 的事务处理过程本质上是一个两阶段提交(2PC)的演进。
我们以一个经典的电商场景为例:订单服务(TM & RM) 调用 库存服务(RM)。
整个交互流程如下:
🚀 第一阶段:执行阶段(Phase 1)
- 开启全局事务:业务发起方(订单服务)的 TM 向 TC 申请开启全局事务。TC 创建全局事务后,返回一个全局唯一的 XID。
- 传递 XID:订单服务在调用库存服务时,会通过 RPC 通信(如 Feign、Dubbo)将 XID 传递给库存服务,将多个服务串联在同一个上下文中。
- 执行分支事务 1(订单服务):
- 订单服务的 RM 拦截数据库操作,向 TC 注册分支事务(携带 XID)。
- 执行本地 SQL,并记录回滚日志(Undo Log)。
- 提交本地数据库事务,释放本地锁。
- 向 TC 汇报分支事务执行状态(成功)。
- 执行分支事务 2(库存服务):
- 库存服务的 RM 获取到 XID,向 TC 注册分支事务。
- 执行本地 SQL(扣减库存),记录回滚日志(Undo Log)。
- 提交本地数据库事务,释放本地锁。
- 向 TC 汇报分支事务执行状态(成功)。
(注意:在第一阶段,各个微服务的本地事务其实已经提交到了数据库,这就是 Seata AT 模式性能高的原因,它不长时间占用数据库锁)
🚀 第二阶段:决断阶段(Phase 2)
这个阶段分为两种情况:全局提交 或 全局回滚。
情况 A:所有业务均执行成功(全局提交)
- 发起提交决断:TM 发现所有的业务逻辑均未报错,向 TC 发起全局提交(Global Commit)请求(携带 XID)。
- 通知各个 RM:TC 收到请求后,将全局事务状态改为 Committing,并向该 XID 下所有注册的 RM 发送提交指令。
- RM 异步清理:各个微服务的 RM 收到提交指令后,会立即给 TC 返回成功。然后把它放入一个异步任务队列中,异步清理本地的
undo_log记录(因为数据已经确定要持久化了,回滚日志没用了)。
情况 B:某处业务执行失败抛出异常(全局回滚)
- 发起回滚决断:TM 捕获到了业务异常(比如库存不足),向 TC 发起全局回滚(Global Rollback)请求(携带 XID)。
- 通知各个 RM:TC 收到请求后,将全局事务状态改为 Rollbacking,并向该 XID 下所有注册的 RM 发送回滚指令。
- RM 执行回滚:各个微服务的 RM 收到回滚指令后,根据第一阶段记录的
undo_log(回滚日志),生成反向 SQL(比如第一阶段是 INSERT,这里就是 DELETE)并执行,恢复本地数据。 - 汇报结果:RM 清理
undo_log,并向 TC 汇报回滚完成。TC 在收到所有 RM 的回滚成功消息后,关闭全局事务。
三、 总结与图解
可以用一张简化的文字图来记忆这个流程:
plaintext
[微服务 A - 发起方] [Seata Server] [微服务 B - 参与方]
TM RM1 TC RM2
| | | |
|--- 1.开启全局事务,获取 XID ------------->| |
| | | |
|--- 2.微服务调用,传递 XID (RPC) ------------------------------------------>|
| | | |
| |--- 3.注册分支事务(XID) ------->| |
| |--- 4.执行本地 SQL + UndoLog | |
| |--- 5.上报分支状态 ------------>| |
| | | |
| | |<--- 6.注册分支事务(XID) -------|
| | | 7.执行本地 SQL + UndoLog --|
| | |<--- 8.上报分支状态 ------------|
| | | |
|--- 9.业务成功,发起全局 Commit ---------->| (或者业务失败,发起全局 Rollback) |
| | |
| |---- 10.通知 RM1 提交/回滚 ---->|
|<---- 11.通知 RM2 提交/回滚 ---------------| |
一句话总结:
TM 是拉开帷幕和决定结局的人;TC 是统筹全局、记录状态的上帝视角;RM 是真正在一线干活,并根据 TC 指令做最后善后(清理日志或反向补偿)的人。而它们之间传递的核心信物就是 XID。