news 2026/3/1 7:34:47

Alibaba分布式事务组件Seata AT模式深度解析与实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Alibaba分布式事务组件Seata AT模式深度解析与实战

一、分布式事务基础概念

1.1 本地事务 vs 分布式事务

在传统单数据库应用中,我们通常使用本地事务来保证数据的一致性。本地事务的ACID特性由数据库直接支持:

java

// JDBC本地事务示例 Connection conn = dataSource.getConnection(); // 获取数据库连接 conn.setAutoCommit(false); // 开启事务 try { // 执行增删改查SQL操作 // update account set balance = balance - 100 where id = 1; // update account set balance = balance + 100 where id = 2; conn.commit(); // 提交事务 } catch (Exception e) { conn.rollback(); // 事务回滚 } finally { conn.close(); // 关闭连接 }

本地事务特点:

  • 操作单一数据库

  • ACID特性由数据库保证

  • 性能高,实现简单

1.2 分布式事务的挑战

在微服务架构下,一个业务操作可能跨越多个服务、多个数据库:

text

用户下单 → 订单服务(DB1) → 库存服务(DB2) → 账户服务(DB3)

典型的分布式事务场景:

  1. 跨库事务:一个服务需要操作多个不同的数据库

  2. 分库分表:数据水平拆分到多个数据库实例

  3. 微服务调用链:多个服务协同完成一个业务操作

面临的挑战:

  • 如何保证多个数据库操作的原子性?

  • 如何协调不同服务的提交或回滚?

  • 如何在高并发下保证性能?

二、两阶段提交(2PC)协议

2.1 2PC工作原理

两阶段提交协议是分布式事务的基础理论,分为两个阶段:

第一阶段:准备阶段(Prepare)

text

事务协调者(TC) → 询问 → 所有参与者(RM) 参与者执行事务操作但不提交,锁定资源 参与者回复:准备好(Yes) / 未准备好(No)

第二阶段:提交/回滚阶段(Commit/Rollback)

text

如果所有参与者都回复Yes: TC → 发送Commit → 所有RM RM提交事务,释放资源 如果有参与者回复No或超时: TC → 发送Rollback → 所有RM RM回滚事务,释放资源

2.2 2PC存在的问题

  1. 同步阻塞:参与者需要锁定资源直到第二阶段完成

  2. 单点故障:协调者故障会导致整个事务阻塞

  3. 数据不一致:第二阶段协调者崩溃可能导致部分参与者提交,部分回滚

  4. 性能问题:长时间的锁等待影响系统吞吐量

三、Seata分布式事务解决方案

3.1 Seata简介

Seata(Simple Extensible Autonomous Transaction Architecture)是阿里巴巴开源的分布式事务解决方案,支持多种事务模式:

  • AT模式(自动补偿):对业务无侵入,推荐使用

  • TCC模式(手动补偿):高性能,需要业务实现try/confirm/cancel

  • Saga模式:长事务解决方案

  • XA模式:基于XA协议的标准实现

3.2 Seata三大核心角色

text

┌─────────────────────────────────────────┐ │ Seata Architecture │ ├─────────────────────────────────────────┤ │ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ TM │────▶│ TC │ │ │ │ (事务管理器)│ │ (事务协调者)│ │ │ └─────────────┘ └─────────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ RM │◀────│ RM │ │ │ │ (资源管理器)│ │ (资源管理器)│ │ │ └─────────────┘ └─────────────┘ │ │ │ └─────────────────────────────────────────┘
  1. TC(Transaction Coordinator):事务协调者

    • 独立部署的Server端服务

    • 维护全局事务和分支事务的状态

    • 驱动全局事务提交或回滚

  2. TM(Transaction Manager):事务管理器

    • 嵌入在业务应用中

    • 定义全局事务边界(开始、提交、回滚)

    • 通过@GlobalTransactional注解标记事务方法

  3. RM(Resource Manager):资源管理器

    • 嵌入在业务应用中

    • 管理分支事务的资源(数据库连接)

    • 向TC注册分支事务并报告状态

3.3 Seata事务生命周期

text

1. TM → TC: 开启全局事务,生成XID XID: 全局唯一事务ID,在调用链中传递 2. RM → TC: 注册分支事务 将本地事务关联到全局事务XID 3. 业务执行阶段 各服务执行业务SQL,生成undo_log 4. TM → TC: 提交/回滚全局事务 根据业务结果决定事务最终状态 5. TC → RM: 驱动分支事务提交/回滚 异步执行第二阶段操作

四、Seata Server环境搭建

4.1 部署模式选择

Seata Server支持三种存储模式:

模式说明适用场景
file单机模式,数据存本地文件开发测试环境
db高可用模式,数据存数据库生产环境,需要高可用
redis高性能模式,数据存Redis高性能场景

4.2 DB模式 + Nacos部署步骤

步骤1:下载Seata Server

bash

# 从GitHub下载 wget https://github.com/seata/seata/releases/download/v1.7.0/seata-server-1.7.0.zip unzip seata-server-1.7.0.zip cd seata
步骤2:创建数据库表

执行MySQL脚本创建Seata Server所需表结构:

sql

-- 创建seata数据库 CREATE DATABASE IF NOT EXISTS seata; USE seata; -- 执行官方提供的建表脚本 -- 下载地址:https://github.com/seata/seata/blob/v1.7.0/script/server/db/mysql.sql -- 主要包含:global_table、branch_table、lock_table等
步骤3:配置Nacos注册中心

修改conf/application.yml

yaml

seata: registry: type: nacos nacos: application: seata-server server-addr: 127.0.0.1:8848 group: SEATA_GROUP namespace: your-namespace-id cluster: default
步骤4:配置Nacos配置中心
  1. 修改conf/application.yml配置中心设置:

yaml

seata: config: type: nacos nacos: server-addr: 127.0.0.1:8848 namespace: your-namespace-id group: SEATA_GROUP data-id: seataServer.properties
  1. 上传配置到Nacos:

bash

# 修改script/config-center/config.txt store.mode=db store.db.driverClassName=com.mysql.cj.jdbc.Driver store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&rewriteBatchedStatements=true store.db.user=root store.db.password=your_password # 事务分组配置 service.vgroupMapping.default_tx_group=default service.default.grouplist=127.0.0.1:8091
步骤5:启动Seata Server

bash

# Linux/Mac ./bin/seata-server.sh # Windows .\bin\seata-server.bat

访问控制台:http://localhost:7091
默认账号密码:seata/seata

五、微服务整合Seata AT模式实战

5.1 业务场景:用户下单

模拟电商下单场景,涉及三个微服务:

  • 订单服务:创建订单记录

  • 库存服务:扣减商品库存

  • 账户服务:扣减用户余额

5.2 环境准备

版本兼容性
组件版本
Spring Boot3.0.2
Spring Cloud2022.0.0
Spring Cloud Alibaba2022.0.0.0
Seata1.7.0
父POM依赖管理

xml

<dependencyManagement> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2022.0.0.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

5.3 微服务配置

1. 添加依赖

xml

<!-- Seata分布式事务 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> </dependency> <!-- 数据库相关 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> </dependency>
2. 创建undo_log表(AT模式必需)

在每个微服务的业务数据库中执行:

sql

CREATE TABLE IF NOT EXISTS `undo_log` ( `branch_id` BIGINT NOT NULL COMMENT 'branch transaction id', `xid` VARCHAR(128) NOT NULL COMMENT 'global transaction id', `context` VARCHAR(128) NOT NULL COMMENT 'undo_log context, such as serialization', `rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info', `log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status', `log_created` DATETIME(6) NOT NULL COMMENT 'create datetime', `log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime', UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`), INDEX `ix_log_created` (`log_created`) ) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table';
3. 配置application.yml

yaml

spring: application: name: order-service datasource: url: jdbc:mysql://localhost:3306/order_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver seata: application-id: ${spring.application.name} # 事务分组,需要与Server端配置对应 tx-service-group: default_tx_group registry: type: nacos nacos: application: seata-server server-addr: 127.0.0.1:8848 group: SEATA_GROUP namespace: your-namespace-id config: type: nacos nacos: server-addr: 127.0.0.1:8848 group: SEATA_GROUP namespace: your-namespace-id data-id: seataServer.properties # 开启数据源代理(必须) enable-auto-data-source-proxy: true
4. 数据源配置类

java

@Configuration public class DataSourceConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource dataSource() { return new DruidDataSource(); } // Seata会自动代理数据源,无需手动配置 // 注意:不能使用@Primary注解,否则会与Seata的代理冲突 }

5.4 业务代码实现

1. 订单服务(事务发起者)

java

@Service @Slf4j public class OrderServiceImpl implements OrderService { @Autowired private OrderMapper orderMapper; @Autowired private StorageFeignService storageFeignService; @Autowired private AccountFeignService accountFeignService; @Override @GlobalTransactional( name = "createOrder", // 全局事务名称 rollbackFor = Exception.class, // 回滚异常类型 timeoutMills = 30000 // 超时时间(毫秒) ) public Order saveOrder(OrderVo orderVo) { log.info("========= 用户下单 ========="); log.info("当前XID: {}", RootContext.getXID()); // 1. 创建订单(本地事务) Order order = new Order(); order.setUserId(orderVo.getUserId()); order.setCommodityCode(orderVo.getCommodityCode()); order.setCount(orderVo.getCount()); order.setMoney(orderVo.getMoney()); order.setStatus(0); // 初始状态 int saveResult = orderMapper.insert(order); log.info("保存订单{}", saveResult > 0 ? "成功" : "失败"); // 2. 扣减库存(远程调用) log.info("开始扣减库存,商品: {}, 数量: {}", orderVo.getCommodityCode(), orderVo.getCount()); ResponseResult<Void> storageResult = storageFeignService.deduct( orderVo.getCommodityCode(), orderVo.getCount() ); if (!storageResult.isSuccess()) { throw new BusinessException("扣减库存失败"); } // 3. 扣减余额(远程调用) log.info("开始扣减余额,用户: {}, 金额: {}", orderVo.getUserId(), orderVo.getMoney()); ResponseResult<Void> accountResult = accountFeignService.debit( orderVo.getUserId(), orderVo.getMoney() ); if (!accountResult.isSuccess()) { throw new BusinessException("扣减余额失败"); } // 4. 更新订单状态 order.setStatus(1); // 成功状态 orderMapper.updateById(order); log.info("订单状态更新成功,订单ID: {}", order.getId()); return order; } }
2. 库存服务

java

@Service @Slf4j public class StorageServiceImpl implements StorageService { @Autowired private StorageMapper storageMapper; @Override public void deduct(String commodityCode, Integer count) { log.info("库存服务 - 扣减库存开始,XID: {}", RootContext.getXID()); // 查询当前库存 Storage storage = storageMapper.selectByCommodityCode(commodityCode); if (storage == null) { throw new BusinessException("商品不存在"); } if (storage.getCount() < count) { throw new BusinessException("库存不足"); } // 扣减库存 storage.setCount(storage.getCount() - count); storageMapper.updateById(storage); log.info("库存服务 - 扣减库存成功,商品: {}, 剩余库存: {}", commodityCode, storage.getCount()); } }
3. 账户服务

java

@Service @Slf4j public class AccountServiceImpl implements AccountService { @Autowired private AccountMapper accountMapper; @Override public void debit(Long userId, BigDecimal money) { log.info("账户服务 - 扣减余额开始,XID: {}", RootContext.getXID()); // 查询账户 Account account = accountMapper.selectById(userId); if (account == null) { throw new BusinessException("账户不存在"); } if (account.getBalance().compareTo(money) < 0) { throw new BusinessException("余额不足"); } // 扣减余额 account.setBalance(account.getBalance().subtract(money)); accountMapper.updateById(account); log.info("账户服务 - 扣减余额成功,用户: {}, 剩余余额: {}", userId, account.getBalance()); } }

5.5 测试验证

测试1:正常下单

bash

# 正常请求 POST http://localhost:8080/order/create Content-Type: application/json { "userId": 1, "commodityCode": "P001", "count": 1, "money": 100.00 } # 预期结果:订单创建成功,库存扣减,余额扣减
测试2:模拟异常回滚

java

// 在账户服务中模拟异常 @Service @Slf4j public class AccountServiceImpl implements AccountService { @Override public void debit(Long userId, BigDecimal money) { // ... 正常业务逻辑 // 模拟异常 if (money.compareTo(new BigDecimal("50")) > 0) { throw new RuntimeException("模拟余额扣减异常"); } // ... 剩余逻辑 } }

预期结果:

  • 订单服务:事务回滚,订单记录被删除

  • 库存服务:事务回滚,库存数量恢复

  • 账户服务:未执行扣减操作

六、Seata AT模式设计原理

6.1 AT模式核心机制

AT模式是一种无侵入的分布式事务解决方案,其核心原理:

text

第一阶段(执行阶段): 1. 执行业务SQL 2. 解析SQL,生成前镜像(before image)和后镜像(after image) 3. 将前后镜像保存到undo_log表 4. 提交本地事务,释放锁资源 第二阶段(完成阶段): - 如果全局事务提交:异步删除undo_log - 如果全局事务回滚:根据undo_log中的前镜像恢复数据

6.2 执行流程详解

第一阶段:分支事务执行

sql

-- 业务SQL示例 UPDATE product SET stock = stock - 1 WHERE id = 1 AND stock > 0; -- Seata代理后执行的操作: -- 1. 查询前镜像(before image) SELECT id, stock FROM product WHERE id = 1; -- 2. 执行业务SQL UPDATE product SET stock = stock - 1 WHERE id = 1 AND stock > 0; -- 3. 查询后镜像(after image) SELECT id, stock FROM product WHERE id = 1; -- 4. 插入undo_log INSERT INTO undo_log (xid, branch_id, rollback_info, log_status) VALUES ('全局事务XID', '分支事务ID', '前后镜像数据', 0); -- 5. 提交本地事务 COMMIT;
第二阶段:全局事务完成

提交场景:

text

TC → 所有RM:提交请求 RM → 删除对应的undo_log记录 完成

回滚场景:

text

TC → 所有RM:回滚请求 RM → 查询undo_log获取前镜像 RM → 根据前镜像生成反向SQL并执行 RM → 删除undo_log记录 完成

6.3 AT模式优势

  1. 无侵入性:业务代码无需改造,只需添加注解

  2. 高性能:一阶段提交本地事务,释放锁资源

  3. 高可用:支持Seata Server集群部署

  4. 强一致性:通过undo_log保证最终数据一致性

  5. 自动补偿:回滚时自动生成反向SQL

6.4 AT模式限制

  1. 仅支持关系型数据库:MySQL、Oracle、PostgreSQL等

  2. SQL解析限制:不支持复杂SQL(如子查询、多表关联更新)

  3. 全局锁机制:更新同一行数据时会产生全局锁竞争

  4. undo_log表管理:需要定期清理历史数据

七、生产环境最佳实践

7.1 性能优化配置

yaml

seata: # 客户端配置 client: rm-report-success-enable: false # 是否上报成功状态,生产环境关闭 rm-table-meta-check-enable: false # 自动刷新表元数据,生产环境关闭 lock: retry-interval: 10 # 获取全局锁重试间隔(毫秒) retry-times: 30 # 获取全局锁重试次数 # 服务端配置(seataServer.properties) service: disableGlobalTransaction: false # 是否禁用全局事务 store: db: max-wait: 5000 # 连接池最大等待时间 query-limit: 100 # 查询限制 transport: thread-factory: boss-thread-prefix: NettyBoss # boss线程前缀 worker-thread-prefix: NettyServerNIOWorker server-executor-thread-prefix: NettyServerBizHandler share-boss-worker: false # 是否共享boss线程 client-selector-thread-prefix: NettyClientSelector client-selector-thread-size: 1 client-worker-thread-prefix: NettyClientWorkerThread

7.2 监控与运维

1. Seata控制台监控

访问Seata Server控制台(默认端口7091):

  • 查看全局事务状态

  • 监控分支事务执行情况

  • 分析事务执行时间

2. 集成Prometheus监控

yaml

# application.yml management: endpoints: web: exposure: include: prometheus,health,info metrics: export: prometheus: enabled: true
3. 日志配置

yaml

logging: level: io.seata: DEBUG com.alibaba.cloud.seata: INFO file: name: logs/seata-client.log max-size: 50MB max-history: 30

7.3 故障排查指南

常见问题1:无法获取全局锁

现象Could not get global lock错误

原因:多个事务同时更新同一行数据

解决方案

  1. 优化业务逻辑,减少热点数据竞争

  2. 调整锁等待时间和重试次数

  3. 使用TCC模式替代AT模式

常见问题2:undo_log表过大

现象:磁盘空间不足,查询性能下降

解决方案

  1. 定期清理历史undo_log

sql

-- 清理7天前的undo_log DELETE FROM undo_log WHERE log_created < DATE_SUB(NOW(), INTERVAL 7 DAY);
  1. 配置自动清理任务

java

@Scheduled(cron = "0 0 2 * * ?") // 每天凌晨2点执行 public void cleanUndoLog() { // 清理逻辑 }
常见问题3:XID未传递

现象:分支事务无法关联到全局事务

解决方案

  1. 确保Feign/RestTemplate等HTTP客户端正确传递XID

  2. 检查网络拦截器是否过滤了XID头

  3. 验证微服务间的网络连通性

八、总结与展望

8.1 Seata AT模式适用场景

推荐使用场景:

  • 业务逻辑相对简单,SQL不复杂

  • 对性能要求较高,希望事务尽快提交

  • 希望业务代码无侵入改造

  • 主要使用MySQL等关系型数据库

不推荐场景:

  • 涉及复杂SQL(多表关联、子查询)

  • 需要处理非关系型数据库

  • 业务对实时一致性要求极高

8.2 与其他模式对比

特性AT模式TCC模式Saga模式
侵入性无侵入需要编码需要编码
性能
一致性最终一致强一致最终一致
复杂度
适用场景简单业务复杂业务长事务

8.3 学习资源推荐

  1. 官方文档:https://seata.io/zh-cn/

  2. GitHub仓库:https://github.com/seata/seata

  3. 实战示例:https://github.com/seata/seata-samples

分布式事务是微服务架构中的关键技术点,选择合适的解决方案对系统稳定性至关重要。Seata AT模式以其无侵入性和易用性,成为大多数场景下的首选方案。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/28 14:43:38

程序猿必学!RAG系统性能提升秘籍:从-5%到+6%的数据工程魔法

检索增强生成&#xff08;Retrieval-Augmented Generation, RAG&#xff09;系统通过结合密集检索和大型语言模型生成能力&#xff0c;在文档问答任务中展现出巨大潜力。然而&#xff0c;传统RAG系统严重依赖预训练词嵌入的语义质量&#xff0c;这些嵌入在专业领域常出现语义漂…

作者头像 李华
网站建设 2026/2/26 21:11:29

量子算法如何优化深度学习训练?

作者:DREAMVFIA UNION 发布日期:2026年1月31日 本文首发于:CSDN技术博客、技术论坛 摘要 随着深度学习模型规模的持续膨胀与参数空间的指数级增长,传统经典计算方法在模型训练效率、参数空间搜索以及全局最优解求解等方面面临着前所未有的瓶颈。本文深入探讨量子计算范式…

作者头像 李华
网站建设 2026/2/23 20:43:31

为什么说量子AI是下一个“ChatGPT时刻“

——一场即将重塑全球科技格局的技术革命与投资机遇深度剖析 发布日期:2026年1月31日 作者:DREAMVFIA UNION © 2026 DREAMVFIA UNION 引言:当历史再次重演 历史总是以出人意料的方式重演。2012年深度学习在ImageNet竞赛中取得突破性进展时,很少有人预见到这将开启一个…

作者头像 李华
网站建设 2026/2/24 4:04:40

【小程序毕设源码分享】基于springboot+Android的考试模拟系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/3/1 5:37:55

学霸同款8个降AIGC工具 千笔·降AIGC助手帮你降AI率

学霸同款8个降AIGC工具 千笔降AIGC助手帮你降AI率 AI降重工具&#xff0c;助你轻松应对论文查重难题 随着人工智能技术的快速发展&#xff0c;越来越多的学生在撰写论文时开始使用AI辅助工具来提升写作效率。然而&#xff0c;AI生成的内容往往存在明显的“AI痕迹”&#xff0…

作者头像 李华