【分布式】分布式事务框架 Seata 详解:架构与四种实现模式

文章目录

    • [一、Seata 的整体架构](#一、Seata 的整体架构)
    • 二、四种实现模式详解
      • [1. AT 模式(Automatic Transaction):非入侵式自动补偿](#1. AT 模式(Automatic Transaction):非入侵式自动补偿)
      • [2. TCC 模式(Try-Confirm-Cancel):业务补偿式](#2. TCC 模式(Try-Confirm-Cancel):业务补偿式)
      • [3. Saga 模式:长事务补偿序列](#3. Saga 模式:长事务补偿序列)
      • [4. XA 模式:标准两阶段提交](#4. XA 模式:标准两阶段提交)
    • 三、四种模式的比较
    • 四、快速上手:
      • 环境准备
      • [步骤1:设置 Seata Server](#步骤1:设置 Seata Server)
      • [步骤2:集成到应用(以 Spring Boot 为例)](#步骤2:集成到应用(以 Spring Boot 为例))
      • 步骤3:编写简单示例

一定要先看完这篇文章:分布式事务的几种概念模型

在微服务和分布式系统盛行的时代,数据一致性成为核心挑战。Seata(Simple Extensible Autonomous Transaction Architecture)作为阿里巴巴开源的分布式事务解决方案,已成为行业标杆。 自 2019 年开源以来,它提供了高效、易用的分布式事务服务,支持多种数据库和中间件。 Seata 的核心在于其四种事务模式:AT、TCC、Saga 和 XA,这些模式从非入侵式到补偿式,覆盖了不同业务场景。

本文将从 Seata 的整体架构入手,逐一剖析这四种模式,帮助你理解其原理、实现和应用。无论你是架构师还是开发者,这都能让你更好地整合 Seata 到项目中。

一、Seata 的整体架构

Seata 采用经典的分布式事务架构,分为三个组件:

  • Transaction Coordinator (TC):事务协调器,负责全局事务的管理、分支事务的注册和状态协调。
  • Transaction Manager ™ :事务管理器,位于应用侧,负责开启、提交或回滚全局事务。通过注解如 @GlobalTransactional 集成。
  • Resource Manager (RM):资源管理器,处理分支事务的数据库或资源层操作,如 SQL 解析和数据快照。

这种设计让 Seata 支持异构系统(如 MySQL、Oracle、PostgreSQL),并兼容 Spring Cloud、Dubbo 等框架。 下面是一个 Seata 架构示意图,展示了组件交互:

Seata 的四种模式基于这个架构,提供从强一致到最终一致的灵活选择。

二、四种实现模式详解

Seata 的模式设计考虑了入侵度、性能和一致性。以下逐一展开。

1. AT 模式(Automatic Transaction):非入侵式自动补偿

AT 是 Seata 的 flagship 模式,旨在提供"无入侵"的分布式事务体验。 它基于两阶段提交(2PC),但通过自动生成 undo log实现回滚。

  • 原理:第一阶段,RM 拦截 SQL,生成 before/after 镜像,并执行本地事务提交。第二阶段,如果全局提交,释放锁;如果回滚,使用 undo log 逆向补偿。
  • 优点:0代码侵入,支持读隔离,性能较高。全局锁机制防止脏写。
  • 缺点:依赖 RDBMS,支持有限(需 JDBC 支持);undo log 占用存储。
  • 适用场景:关系型数据库主导的微服务,如电商订单扣库存和扣款。

AT 模式在 Seata 控制台中支持全局锁手动控制。

2. TCC 模式(Try-Confirm-Cancel):业务补偿式

TCC 是柔性事务模式,将事务拆分成 Try(预留资源)、Confirm(确认)和 Cancel(取消)。开发者需手动实现这些接口。

  • 原理:TM 协调各 RM 执行 Try,如果全成功则 Confirm;否则 Cancel。Seata 通过注解确保幂等和重试。
  • 优点:高性能、无全局锁,支持 NoSQL 和自定义逻辑。最终一致性,适用于高并发。
  • 缺点:业务入侵强,实现复杂。
  • 适用场景:资源预留业务,如支付系统的余额冻结和解冻。

Seata 的 TCC 支持分支事务嵌套,提升灵活性。

3. Saga 模式:长事务补偿序列

Saga 适合长链事务,将全局事务拆分成子事务序列,每个有正向和补偿操作。

  • 原理:Seata 支持状态机式和注解式实现。协调器按序执行子事务,失败时逆序补偿。支持事件驱动。
  • 优点:高可用、无锁,适合复杂流程。易扩展到异步场景。
  • 缺点:最终一致,非实时;补偿逻辑需自定义,可能有短暂不一致窗口。
  • 适用场景:多步骤业务,如旅游预订(订票、酒店、保险)。

Seata Saga 提供最佳实践,如异常处理和持久化状态。

4. XA 模式:标准两阶段提交

XA 是基于数据库 XA 协议的模式,提供强一致性。

  • 原理:第一阶段 prepare,第二阶段 commit/rollback。Seata 的 TC 充当协调器,RM 使用数据库 XA 接口。
  • 优点:强一致、原子性保证,支持标准数据库。
  • 缺点:长时间锁定、易阻塞,不适合高并发。
  • 适用场景:遗留系统或需 ACID 的金融交易。

XA 在 Seata 中作为补充,常与 AT 混合使用。

三、四种模式的比较

模式 一致性 入侵度 性能 适用
AT 强(全局锁) 中高 RDBMS 微服务
TCC 最终 高并发补偿
Saga 最终 长链业务
XA 传统 ACID

四、快速上手:

环境准备

上手 Seata 前,确保满足以下要求:

  • JDK 8+:Seata 支持 Java 环境。
  • 数据库:MySQL 5.7+(InnoDB 引擎),其他如 Oracle、PostgreSQL 也支持。
  • 依赖管理:Maven 或 Gradle,用于构建示例项目。
  • 下载 Seata Server:从 GitHub releases 下载最新 zip 包(e.g., seata-server-2.x.zip)。

对于示例,我们用一个电商场景:用户购买商品,涉及库存扣减、订单创建和账户扣款。这些操作分布在三个微服务中,但你可以先用单一数据库模拟。

要注意确保数据库使用 InnoDB 引擎,否则回滚不支持。

步骤1:设置 Seata Server

Seata Server 是事务协调器(TC),负责全局事务管理。

  1. 解压包:下载并解压 seata-server-xxx.zip。
  2. 启动 Server
    • Linux/Mac:sh ./bin/seata-server.sh --host 0.0.0.0 --port 8091 --storeMode file(file 模式适合测试,db 模式用于生产)。
    • Windows:cmd ./bin/seata-server.bat
  3. 验证:访问 http://localhost:7091(控制台端口),或检查日志确认启动成功。

生产建议:用 Nacos 或 Etcd 作为配置/注册中心,提升高可用。

步骤2:集成到应用(以 Spring Boot 为例)

Seata 集成简单,尤其 AT 模式无业务入侵。

  1. 添加依赖 :在 pom.xml 中引入 Seata Starter。

    xml 复制代码
    <dependency>
        <groupId>io.seata</groupId>
        <artifactId>seata-spring-boot-starter</artifactId>
        <version>2.x</version> <!-- 匹配 server 版本 -->
    </dependency>
  2. 配置 application.yml

    yaml 复制代码
    seata:
      enabled: true
      application-id: business-service
      tx-service-group: my_test_tx_group
      registry:
        type: file  # 或 nacos
      config:
        type: file  # 或 nacos
    spring:
      datasource:  # 配置数据源
        url: jdbc:mysql://localhost:3306/test_db
  3. 创建 UNDO_LOG 表 (AT 模式必备,用于回滚快照):

    sql 复制代码
    CREATE TABLE IF NOT EXISTS `undo_log` (
      `branch_id` BIGINT NOT NULL,
      `xid` VARCHAR(128) NOT NULL,
      `context` VARCHAR(128) NOT NULL,
      `rollback_info` LONGBLOB NOT NULL,
      `log_status` INT NOT NULL,
      `log_created` DATETIME(6) NOT NULL,
      `log_modified` DATETIME(6) NOT NULL,
      UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

    在每个参与事务的数据库中执行此脚本。

对于其他模式:

  • TCC :实现 Try/Confirm/Cancel 接口,并用 @TwoPhaseBusinessAction 注解。
  • Saga:定义状态机 JSON 或注解,配置补偿逻辑。
  • XA:启用 XA 数据源,无需额外表,但性能较低。

步骤3:编写简单示例

用官方电商示例快速验证。

  1. 克隆示例项目git clone https://github.com/apache/incubator-seata-samples.git,切换到 at-sample 分支。

  2. 创建数据库表

    • storage_tbl:库存表(commodity_code, count)。
    • order_tbl:订单表(user_id, commodity_code, count, money)。
    • account_tbl:账户表(user_id, money)。
      示例 SQL 在官方仓库 script/client/at/db/mysql.sql。
  3. 添加 @GlobalTransactional

    java 复制代码
    @GlobalTransactional(name = "purchase", rollbackFor = Exception.class)
    public void purchase(String userId, String commodityCode, int orderCount) {
        storageService.deduct(commodityCode, orderCount);  // 扣库存
        orderService.create(userId, commodityCode, orderCount);  // 创建订单,扣款
    }
  4. 运行:启动 Storage、Order、Account 和 Business 服务。调用 purchase 接口,模拟失败(如库存不足),观察回滚。

如果用 Dubbo:配置 dubbo-provider.xml,并确保服务注册到 Seata。

Choose the right pattern, solve the right problem!

相关推荐
华如锦9 小时前
四:从零搭建一个RAG
java·开发语言·人工智能·python·机器学习·spring cloud·计算机视觉
Tony_yitao9 小时前
22.华为OD机试真题:数组拼接(Java实现,100分通关)
java·算法·华为od·algorithm
JavaGuru_LiuYu9 小时前
Spring Boot 整合 SSE(Server-Sent Events)
java·spring boot·后端·sse
xuejianxinokok9 小时前
如何在 Rust 中以惯用方式使用全局变量
后端·rust
爬山算法9 小时前
Hibernate(26)什么是Hibernate的透明持久化?
java·后端·hibernate
彭于晏Yan9 小时前
Springboot实现数据脱敏
java·spring boot·后端
做cv的小昊9 小时前
【TJU】信息检索与分析课程笔记和练习(6)英文数据库检索—web of science
大数据·数据库·笔记·学习·全文检索
每天吃饭的羊9 小时前
媒体查询
开发语言·前端·javascript
luming-029 小时前
java报错解决:sun.net.utils不存
java·经验分享·bug·.net·intellij-idea
北海有初拥9 小时前
Python基础语法万字详解
java·开发语言·python