Seata 原理与源码解析:分布式事务的终极解法 - 实践

在这里插入图片描述

在微服务架构中,一个完整的业务往往会拆分成多个服务调用。
比如「下单」 → 涉及订单服务、库存服务、支付服务,这时就会遇到一个难题:如何保证跨服务的一致性?

为了解决这个问题而生的。就是Seata 就


一、为什么需要 Seata?

传统单体应用里,事务依赖数据库的ACID 特性,MySQL 一条 BEGIN … COMMIT 就能搞定。

但在微服务里:

  • 每个服务都有独立数据库
  • 一个业务可能要跨 3-5 个库
  • 分布式系统有网络延迟、失败风险

这时 本地事务就无能为力了,需要分布式事务协调器来保障全局一致性。


二、Seata 的核心思想

Seata 提供了一个全局事务管理器(TC:Transaction Coordinator),它通过拦截各个服务的本地事务,统一协调提交或回滚。

Seata 支持四种事务模式:

  1. AT 模式(最常用)
    • 自动代理数据库操作
    • 基于 两阶段提交(2PC) 实现:
      • 一阶段保存快照并执行业务 SQL
      • 二阶段提交则清理快照,回滚则用快照还原
    • 适合大多数业务场景
  2. TCC 模式
    • Try-Confirm-Cancel 三阶段事务
    • 需要业务手写三个手段
    • 灵活但开发成本高
  3. Saga 模式
    • 长事务补偿模式
    • 通过状态机和补偿动作保证一致性
  4. XA 模式
    • 基于数据库 XA 协议
    • 强一致性,但性能较差

三、Seata 架构图(竖向结构,避免过宽)

TC (Transaction Coordinator)
维护全局事务状态
协调分支提交/回滚
RM (Resource Manager)
注册分支事务
执行本地事务
报告事务状态
TM (Transaction Manager)
开启全局事务
提交或回滚
全局事务发起方 TM
事务协调器 TC
各业务服务 RM

解读:

  • TM:发起、结束全局事务(相当于老板)。
  • RM:管理具体资源(数据库操控,像工人)。
  • TC:协调大家一起干活(项目经理)。

四、Seata 的执行流程(AT 模式)

假设「下单」场景:订单服务 → 库存服务 → 支付服务。

  1. TM 向 TC发起全局事务
  2. 各服务 RM注册分支事务 到 TC
  3. 本地执行 SQL,同时生成快照(Undo Log)
  4. 假设全部成功,TM 通知 TC 提交 → TC 通知所有 RM 清理 Undo Log
  5. 要是有失败,TC 通知所有 RM回滚→ 读取 Undo Log,恢复数据

五、源码入口解析

Seata 的核心源码许可从以下几个包入手:

  1. TM(事务发起)
    • io.seata.tm.api.GlobalTransaction
    • 入口方法:begin() / commit() / rollback()
  2. RM(资源管理器)
    • io.seata.rm.datasource.DataSourceProxy
    • 拦截 JDBC 操作,生成 Undo Log
  3. TC(协调器)
    • io.seata.server.coordinator.DefaultCoordinator
    • 接收 TM/RM 的请求,维护全局事务状态机
  4. Undo Log 存储
    • undo_log 表:保存快照,用于回滚

六、实战中的坑点

  1. Undo Log 表膨胀
    • 需定期清理已完成事务的快照
  2. 跨服务调用必须带 XID
    • 否则 TC 无法识别事务链路
  3. 性能影响
    • AT 模式性能损耗一般在 10% 左右,需要结合业务选择 TCC 或 Saga

七、总结

一句话记住 Seata:

Seata = TM + RM + TC,帮你把跨服务事务当成本地事务一样用。

对于日常开发:

  • 如果业务简单,直接上AT 模式,几乎零侵入
  • 假如要求高性能且能接受开发成本,用TCC
  • 如果是长事务场景(比如跨天结算),考虑Saga

posted @ 2025-09-21 13:37  wzzkaifa  阅读(13)  评论(0)    收藏  举报