Seata(Simple Extensible Autonomous Transaction Architecture,简单可扩展自治事务架构)是阿里巴巴开源的分布式事务解决方案,核心定位是“解决微服务架构中多服务数据一致性问题”,替代传统复杂的2PC/3PC方案,提供高性能、易用、可扩展的分布式事务支持。
Seata 无缝集成 Spring Cloud、Spring Boot、Spring Cloud Alibaba 及 Dubbo 生态,完美适配微服务场景,核心解决“跨服务数据不一致”痛点(如订单服务创建订单、库存服务扣减库存,一方成功、一方失败导致的数据偏差)。本文将从「核心知识点→底层原理→实战用法→高级特性→常见问题」五个维度,全面讲解 Seata,兼顾理论深度与实战落地,保持与此前 Sentinel 文档一致的逻辑节奏,便于学习和查阅。
一、Seata 核心知识点(必懂基础)
1. Seata 核心定位与设计理念
① 核心定位:微服务分布式事务解决方案,专注于解决跨服务调用时的“数据一致性”问题,支持多种事务模式,兼顾性能与易用性,适配高并发微服务场景。
② 设计理念:“去中心化+自治”,核心是将分布式事务拆分为“本地事务”和“全局事务”,通过事务协调器(TC)、事务管理器(TM)、资源管理器(RM)三者协同,实现“最终一致性”或“强一致性”,避免传统2PC方案的性能瓶颈和阻塞问题。
③ 核心优势(对比传统分布式事务方案):
- 易用性高:无侵入式集成 Spring 生态,通过注解即可实现分布式事务,无需手动编写复杂的事务协调逻辑;
- 性能优异:支持多种事务模式(AT、TCC 等),AT 模式无需手动编写补偿逻辑,性能接近本地事务;
- 灵活性强:支持不同场景的事务需求(强一致性、最终一致性),可根据业务场景选择合适的事务模式;
- 生态适配广:无缝集成 Spring Cloud Alibaba、Dubbo、MyBatis 等主流微服务组件,适配国内企业开发场景。
2. Seata 核心概念(重中之重)
Seata 的分布式事务实现,依赖三个核心角色和一套事务模型,理解这些概念是掌握 Seata 的基础:
(1)核心角色(3个,必记)
Seata 通过三个角色协同工作,实现分布式事务的协调与控制,三者各司其职、缺一不可:
-
TM(Transaction Manager,事务管理器):
- 定位:发起全局事务的“决策者”,负责开启、提交或回滚全局事务;
- 核心操作:向 TC 注册全局事务,协调所有分支事务的提交/回滚,最终决定全局事务的状态;
- 部署位置:嵌入在发起分布式事务的微服务中(如订单服务,作为事务发起方)。
-
RM(Resource Manager,资源管理器):
- 定位:管理本地事务资源的“执行者”,负责执行本地事务,并与 TC 通信,汇报本地事务状态;
- 核心操作:向 TC 注册分支事务,执行本地事务的提交/回滚,接收 TC 的指令;
- 部署位置:嵌入在所有参与分布式事务的微服务中(如订单服务、库存服务、支付服务)。
-
TC(Transaction Coordinator,事务协调器):
- 定位:分布式事务的“协调中心”,独立部署,负责协调 TM 和 RM,维护全局事务和分支事务的状态;
- 核心操作:接收 TM 的全局事务请求,接收 RM 的分支事务注册和状态汇报,向 RM 发送提交/回滚指令;
- 核心作用:保证全局事务和分支事务的状态一致性,是 Seata 分布式事务的核心枢纽。
核心流程简化:TM 发起全局事务 → TC 记录全局事务状态 → RM 注册分支事务并执行本地事务 → TC 协调所有 RM 提交/回滚 → TM 确认全局事务完成。
(2)事务模式(4种,重点掌握前2种)
Seata 支持4种事务模式,适配不同的业务场景,核心差异在于“一致性强度”和“性能”的权衡:
① AT 模式(Auto Transaction,自动事务)—— 推荐,最常用
核心特点:无侵入式、自动补偿,性能优异,适配大多数微服务场景(如订单创建、库存扣减、支付扣款),追求“最终一致性”。
核心原理:基于“本地事务+undo_log 日志”实现,无需手动编写补偿逻辑,Seata 自动完成回滚。
② TCC 模式(Try-Confirm-Cancel,补偿事务)
核心特点:侵入式、手动补偿,灵活性高,适配复杂业务场景(如跨银行转账),追求“强一致性”。
核心原理:将事务拆分为 Try(尝试)、Confirm(确认)、Cancel(取消)三个阶段,需要开发者手动实现三个阶段的逻辑。
③ SAGA 模式
核心特点:长事务模式,适配跨服务长流程场景(如订单履约、物流调度),基于“补偿机制”实现最终一致性,支持异步补偿。
④ XA 模式
核心特点:兼容传统 2PC 方案,强一致性,性能较差(存在阻塞问题),适配传统数据库的分布式事务场景,不推荐微服务高并发场景使用。
(3)核心术语
- 全局事务(Global Transaction):由 TM 发起,包含多个分支事务的分布式事务,最终要么全部提交,要么全部回滚;
- 分支事务(Branch Transaction):RM 执行的本地事务,是全局事务的一部分,受全局事务控制;
- undo_log 日志:AT 模式的核心,用于记录本地事务执行前的数据状态,当需要回滚时,通过 undo_log 日志恢复数据;
- 事务ID(XID):全局事务的唯一标识,用于关联全局事务和分支事务,TM、RM、TC 之间通过 XID 通信。
3. Seata 架构组成
Seata 架构分为「服务端(TC)」和「客户端(TM+RM)」两部分,二者通过网络通信协同工作:
- 服务端(TC):独立部署的分布式事务协调中心,负责维护全局事务和分支事务的状态,协调所有客户端的事务提交/回滚,核心是“事务协调”;
- 客户端(TM+RM):嵌入在微服务应用中,TM 负责发起全局事务,RM 负责执行本地事务并与 TC 通信,核心是“事务执行与反馈”。
补充:Seata 服务端支持集群部署,基于数据库或 Redis 实现高可用,避免 TC 单点故障(企业级部署必备)。
二、Seata 底层原理(深度理解)
Seata 不同事务模式的底层原理差异较大,其中 AT 模式是最常用、最核心的模式,以下重点讲解 AT 模式的底层原理,TCC 模式简要补充,帮助理解 Seata 的核心工作机制。
1. AT 模式底层原理(核心,必懂)
AT 模式的核心是“本地事务提交+异步补偿”,无需手动编写回滚逻辑,Seata 自动完成数据恢复,分为「一阶段(本地事务执行)」和「二阶段(全局事务提交/回滚)」两个阶段,全程无阻塞,性能接近本地事务。
(1)一阶段:本地事务执行(核心步骤)
- TM 发起全局事务,向 TC 申请全局事务 ID(XID),TC 生成 XID 并返回给 TM;
- TM 将 XID 传递给所有参与分布式事务的微服务(如订单服务、库存服务);
- 每个微服务的 RM 接收 XID,向 TC 注册分支事务(关联 XID);
- RM 执行本地事务(如订单插入、库存扣减),同时在本地数据库中生成 undo_log 日志(记录事务执行前的数据状态);
- 本地事务提交,释放数据库锁(核心:一阶段本地事务直接提交,避免阻塞);
- RM 向 TC 汇报分支事务状态(成功/失败)。
(2)二阶段:全局事务提交/回滚(核心步骤)
二阶段由 TC 根据所有分支事务的状态,决定全局事务是“提交”还是“回滚”:
① 全局提交(所有分支事务均成功)
- TC 接收 TM 的全局提交请求,或检测到所有分支事务均成功;
- TC 向所有 RM 发送“分支提交”指令;
- RM 接收指令后,删除本地的 undo_log 日志(无需回滚,日志无用);
- RM 向 TC 汇报分支提交完成,TC 标记全局事务为“已提交”,TM 确认全局事务完成。
② 全局回滚(存在分支事务失败)
- TC 检测到某个分支事务失败,或接收 TM 的全局回滚请求;
- TC 向所有 RM 发送“分支回滚”指令;
- RM 接收指令后,读取本地的 undo_log 日志,根据日志恢复数据(将数据回滚到事务执行前的状态);
- RM 删除 undo_log 日志,向 TC 汇报分支回滚完成;
- TC 标记全局事务为“已回滚”,TM 确认全局事务回滚完成。
(3)关键说明
- undo_log 日志:核心是“数据快照”,记录字段的旧值,回滚时通过旧值恢复数据,仅在 AT 模式中需要;
- 无阻塞优势:一阶段本地事务直接提交,释放数据库锁,避免传统 2PC 一阶段的阻塞问题,性能大幅提升;
- 最终一致性:二阶段回滚是异步执行的,可能存在短暂的数据不一致,但最终会恢复一致,适配大多数微服务场景。
2. TCC 模式底层原理(简要补充)
TCC 模式是侵入式事务模式,需要开发者手动实现三个阶段的逻辑,核心是“手动补偿”,追求强一致性:
- Try 阶段:尝试执行事务,预留资源(如扣减库存前,先锁定库存),不提交最终数据;
- Confirm 阶段:所有 Try 阶段成功,确认执行事务,提交最终数据(如确认扣减库存);
- Cancel 阶段:某个 Try 阶段失败,取消事务,释放预留资源(如解锁库存)。
特点:灵活性高,适配复杂业务,但开发成本高,需要手动编写三个阶段的逻辑,且需保证 Confirm/Cancel 阶段的幂等性(避免重复执行)。
三、Seata 实战用法(重点,可直接落地)
Seata 实战核心是“搭建 TC 服务端→微服务集成 Seata(TM+RM)→配置事务模式→测试分布式事务”,以下基于 Spring Cloud Alibaba + Seata + Nacos + MyBatis 生态,讲解最常用的 AT 模式实战步骤,适配企业开发场景(全程可复制)。
1. 第一步:搭建 Seata 服务端(TC)
TC 是 Seata 分布式事务的协调中心,必须独立部署,支持单机部署和集群部署(企业级推荐集群),以下讲解单机部署步骤(简单易上手):
(1)下载 Seata 服务端包
从 Seata 官方 GitHub 下载最新稳定版(如 seata-server-1.6.1.zip),解压到本地目录(如 D:\seata-server-1.6.1)。
(2)配置 Seata 服务端
进入解压目录的 conf 文件夹,修改核心配置文件(application.yml),主要配置端口、存储模式(事务日志存储方式):
server:
port: 8091 # TC 服务端端口,默认8091,避免端口冲突
spring:
application:
name: seata-server
seata:
config:
type: file # 配置文件类型,单机部署用file,集群用nacos/apollo
registry:
type: nacos # 注册中心类型,与微服务注册中心一致(推荐nacos)
nacos:
server-addr: localhost:8848 # nacos地址(需提前启动nacos)
group: SEATA_GROUP # 注册分组,默认SEATA_GROUP
application: seata-server # TC在nacos中的服务名
store:
mode: db # 存储模式,事务日志存储到数据库(推荐,单机也可用file)
db:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/seata?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
user: root # 数据库用户名
password: 123456 # 数据库密码
min-conn: 5
max-conn: 100
global-table: global_table # 全局事务表
branch-table: branch_table # 分支事务表
lock-table: lock_table # 锁表
distributed-lock-table: distributed_lock # 分布式锁表
log-table: log_table # 日志表
retry-attempts: 3 # 重试次数
retry-interval: 1000 # 重试间隔
(3)初始化 Seata 数据库
-
创建数据库 seata(与上述配置中的 url 对应);
-
执行 Seata 官方提供的数据库初始化脚本(conf 文件夹下的 db_schema.sql),创建 global_table、branch_table 等核心表(用于存储事务日志和状态)。
(4)启动 Seata 服务端
进入解压目录的 bin 文件夹,执行启动命令(Windows 执行 seata-server.bat,Linux 执行 seata-server.sh):
# Windows 启动命令(直接双击 seata-server.bat,或命令行执行)
seata-server.bat -p 8091 -h 127.0.0.1 -m db
# 参数说明
# -p:TC 端口,默认8091
# -h:TC 地址,默认127.0.0.1
# -m:存储模式,db 表示存储到数据库
启动成功后,可在 Nacos 控制台的“服务列表”中看到 seata-server 服务(注册成功)。
2. 第二步:微服务集成 Seata(TM+RM)
以“订单服务(order-service)”和“库存服务(stock-service)”为例,讲解微服务如何集成 Seata,实现分布式事务(AT 模式),两个服务均需集成 Seata。
(1)引入 Seata 依赖
在两个微服务的 pom.xml 中,引入 Seata 核心依赖和 Spring Cloud Alibaba Seata 依赖(确保版本与 Seata 服务端一致):
<!-- Spring Cloud Alibaba Seata 依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2.2.9.RELEASE</version> <!-- 与 Spring Cloud Alibaba 版本匹配 -->
</dependency>
<!-- Seata 核心依赖(若上述依赖未包含,需单独引入) -->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.6.1</version> <!-- 与 Seata 服务端版本一致 --></dependency>
(2)配置微服务(application.yml)
在两个微服务的 application.yml 中,配置 Seata 相关参数,关联 TC 服务端和 Nacos 注册中心:
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848 # nacos地址,与TC一致
alibaba:
seata:
tx-service-group: my_test_tx_group # 事务组名称,需与TC配置一致(默认my_test_tx_group)
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/order_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC # 订单服务数据库(库存服务替换为stock_db)
username: root
password: 123456
# Seata 配置
seata:
registry:
type: nacos # 注册中心类型,与TC一致
nacos:
server-addr: localhost:8848
group: SEATA_GROUP
application: seata-server
tx-service-group: my_test_tx_group # 事务组名称,必须与spring.cloud.alibaba.seata.tx-service-group一致
service:
vgroup-mapping:
my_test_tx_group: default # 事务组与TC集群的映射关系,单机TC用default
grouplist:
default: 127.0.0.1:8091 # TC服务端地址和端口
data-source-proxy-mode: AT # 事务模式,默认AT,无需修改
(3)初始化微服务数据库(undo_log 表)
AT 模式需要在每个微服务的数据库中,创建 undo_log 表(用于存储回滚日志),执行以下 SQL 脚本(每个参与分布式事务的数据库都要执行):
CREATE TABLE `undo_log` (
`id` bigint NOT NULL AUTO_INCREMENT,
`branch_id` bigint NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
`ext` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
示例:订单服务的 order_db 数据库、库存服务的 stock_db 数据库,均需创建 undo_log 表。
(4)标记分布式事务(TM 发起全局事务)
在事务发起方(如订单服务)的业务方法上,添加 @GlobalTransactional 注解(标记为全局事务),该方法即为 TM,负责发起全局事务;参与方(库存服务)无需额外注解,Seata 自动识别为 RM。
① 订单服务(TM,事务发起方)
import com.alibaba.fastjson.JSON;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
// 标记为全局事务,TM 发起全局事务
@GlobalTransactional(name = "createOrderTx", rollbackFor = Exception.class)
@PostMapping("/order/create")
public String createOrder(@RequestBody OrderDTO orderDTO) {
try {
// 1. 本地事务:创建订单(订单服务本地操作)
orderService.createOrder(orderDTO);
// 2. 远程调用:扣减库存(调用库存服务)
String stockResult = stockFeignClient.deductStock(orderDTO.getProductId(), orderDTO.getQuantity());
if (!"success".equals(stockResult)) {
throw new RuntimeException("扣减库存失败");
}
// 3. 远程调用:扣减余额(可选,调用支付服务)
// String payResult = payFeignClient.deductBalance(orderDTO.getUserId(), orderDTO.getAmount());
return "订单创建成功";
} catch (Exception e) {
// 发生异常,TM 向 TC 发起全局回滚请求
throw new RuntimeException("订单创建失败,触发全局回滚:" + e.getMessage());
}
}
}
关键说明:
- @GlobalTransactional:标记全局事务,name 为事务名称(唯一),rollbackFor 表示所有异常都触发回滚;
- 该方法中,本地事务(创建订单)和远程调用(扣减库存)共同组成分布式事务,若任何一步失败,将触发全局回滚。
② 库存服务(RM,事务参与方)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class StockController {
@Autowired
private StockService stockService;
// 无需添加 @GlobalTransactional,Seata 自动识别为 RM,执行本地事务
@PostMapping("/stock/deduct")
public String deductStock(@RequestParam("productId") Long productId, @RequestParam("quantity") Integer quantity) {
// 本地事务:扣减库存
stockService.deductStock(productId, quantity);
return "success";
}
}
关键说明:RM 无需额外注解,Seata 会通过拦截器,自动将该方法的本地事务注册为分支事务,关联全局事务 XID。
3. 第三步:测试分布式事务
启动 Nacos、Seata 服务端、订单服务、库存服务,通过 Postman 调用订单服务的 /order/create 接口,测试两种场景:正常场景和异常场景,验证分布式事务是否生效。
(1)正常场景(所有步骤成功)
请求参数:{"productId":1,"quantity":2,"userId":1001,"amount":100},执行流程:
- 订单服务创建订单(本地事务提交);
- 远程调用库存服务,扣减库存(本地事务提交);
- TM 向 TC 发起全局提交,TC 通知所有 RM 提交分支事务,删除 undo_log 日志;
- 最终:订单表新增数据,库存表减少对应数量,数据一致。
(2)异常场景(某一步失败)
模拟库存扣减失败(如在库存服务中手动抛出异常),执行流程:
- 订单服务创建订单(本地事务提交);
- 远程调用库存服务,扣减库存失败,抛出异常;
- 订单服务捕获异常,TM 向 TC 发起全局回滚请求;
- TC 通知所有 RM 回滚分支事务,RM 读取 undo_log 日志,恢复数据;
- 最终:订单表新增的数据被回滚(删除),库存表数据不变,数据一致。
(3)监控验证
Seata 服务端提供简单的监控页面,访问 http://localhost:8091/seata/index.html,可查看全局事务和分支事务的状态(已提交、已回滚),便于排查问题。
四、Seata 高级特性(进阶拓展)
1. 事务组配置(企业级部署必备)
事务组(tx-service-group)是 Seata 中用于隔离不同业务系统的分布式事务的核心配置,不同业务系统可配置不同的事务组,避免相互影响。
核心配置:在 Seata 服务端的 conf 文件夹下,修改 registry.conf 和 file.conf,配置事务组与 TC 集群的映射关系,实现多业务系统的事务隔离。
2. 规则持久化(高可用部署必备)
Seata 服务端的配置(如事务组、存储模式),默认存储在本地文件中,集群部署时需实现配置持久化,常用方案:
- 基于 Nacos 持久化:将 Seata 配置存储在 Nacos 中,所有 TC 节点从 Nacos 拉取配置,实现配置统一管理;
- 基于 Apollo 持久化:适配使用 Apollo 作为配置中心的场景,配置流程与 Nacos 类似。
3. 集群部署(高可用)
企业级部署中,TC 服务端需集群部署,避免单点故障,核心步骤:
- 部署多个 Seata 服务端节点,修改每个节点的 application.yml,确保注册中心(如 Nacos)配置一致;
- 所有 TC 节点使用同一个数据库(存储事务日志),实现数据共享;
- 微服务配置中,grouplist 配置所有 TC 节点地址,实现负载均衡和故障转移。
4. 与 OpenFeign 集成(微服务通信必备)
微服务中通过 OpenFeign 远程调用时,Seata 自动将 XID 传递给被调用服务,无需额外配置,确保分支事务与全局事务关联。
关键配置:确保微服务引入 OpenFeign 依赖,且 Seata 依赖版本与 Spring Cloud Alibaba 版本匹配,即可自动集成。
5. 幂等性处理(避坑重点)
分布式事务中,由于网络延迟、重试等原因,可能出现重复调用的情况,需保证业务方法的幂等性(重复执行结果一致),常用方案:
- 基于唯一标识(如订单号):执行业务前,先查询是否已执行,避免重复执行;
- 基于 Redis 分布式锁:执行业务前,获取锁,执行完成后释放锁,避免并发重复执行。
五、Seata 常见问题与解决方案(实战避坑)
1. 问题1:微服务启动后,无法连接 Seata 服务端(TC)
解决方案:
- 检查 TC 服务端是否启动,且端口(默认8091)未被占用;
- 检查微服务配置:确保 seata.registry.nacos.server-addr、seata.service.grouplist 配置正确,与 TC 一致;
- 检查事务组名称:微服务的 tx-service-group 必须与 TC 配置的事务组名称一致;
- 检查网络连通性:确保微服务与 TC 服务端在同一网络,无防火墙拦截。
2. 问题2:分布式事务未触发回滚(本地事务提交,远程事务失败,数据不一致)
解决方案:
- 检查事务注解:事务发起方必须添加 @GlobalTransactional 注解,且 rollbackFor 配置正确(如 rollbackFor = Exception.class);
- 检查异常是否抛出:确保远程调用失败后,抛出异常,且异常被 @GlobalTransactional 捕获;
- 检查 undo_log 表:确保参与分布式事务的微服务数据库中,已创建 undo_log 表(AT 模式必需);
- 检查 Seata 版本:确保微服务的 Seata 依赖版本与 TC 服务端版本一致,避免版本不兼容。
3. 问题3:Seata 服务端重启后,未完成的分布式事务丢失
解决方案:将 Seata 服务端的存储模式设置为 db(数据库存储),避免使用 file 模式(本地文件存储,重启后数据丢失),确保事务日志持久化到数据库。
4. 问题4:undo_log 表插入失败,导致本地事务无法提交
解决方案:
- 检查 undo_log 表结构:确保表结构与 Seata 官方提供的脚本一致,尤其是 rollback_info 字段为 longblob 类型;
- 检查数据库权限:确保微服务数据库用户拥有 undo_log 表的插入、更新、删除权限;
- 检查 Seata 配置:确保 data-source-proxy-mode 配置为 AT(默认),避免配置错误导致 undo_log 不插入。
5. 问题5:集群部署时,TC 节点之间数据不一致
解决方案:所有 TC 节点使用同一个数据库(存储事务日志),确保事务数据共享;配置相同的事务组映射关系,避免节点间配置不一致。
六、总结
Seata 作为国内微服务生态的核心分布式事务解决方案,核心价值是“解决跨服务数据一致性问题”,通过 TM、RM、TC 三个角色协同,支持多种事务模式,兼顾性能与易用性,是企业微服务落地的必备组件。
本文延续此前 Sentinel 文档的逻辑结构,从基础知识点、底层原理、实战用法、高级特性到常见问题,全面覆盖 Seata 的核心内容,重点突出 AT 模式的实战落地步骤(可直接复制使用),适配开发和面试需求。
核心要点:掌握 Seata 的三个核心角色、AT 模式的底层原理,能独立完成 Seata 服务端搭建、微服务集成和分布式事务测试,同时掌握规则持久化、集群部署、幂等性处理等高级特性,即可应对企业开发中的大多数分布式事务场景,也能轻松应对面试中的相关提问。