在 Spring Boot 项目中集成 Seata AT 模式 并使用 Nacos 作为注册中心和配置中心,是实现分布式事务的主流方案。以下是 完整、清晰、可操作性强 的配置步骤及说明(适用于 Spring Boot 3.x + Spring Cloud Alibaba 2023.x + Seata 2.0.0+ + Nacos 2.x)。
✅ 一、整体架构说明
- TC(Transaction Coordinator):Seata Server,负责协调全局事务。
- TM(Transaction Manager) :发起全局事务的服务(如订单服务),用
@GlobalTransactional注解。 - RM(Resource Manager):参与分支事务的服务(如库存、支付服务),自动注册到 TC。
- Nacos :同时作为 服务注册中心 和 配置中心。
- AT 模式:基于数据库代理(DataSourceProxy)自动生成 undo_log 实现回滚。
✅ 二、前置准备
| 组件 | 版本建议 |
|---|---|
| JDK | 17 |
| Maven | 3.8+ |
| MySQL | 8.0 |
| Nacos | 2.2.x ~ 2.3.x |
| Seata Server | 2.0.0 |
| Spring Boot | 3.2.x |
| Spring Cloud Alibaba | 2023.0.1.0 |
⚠️ 注意:Seata 2.0.0 起推荐使用 application.yml 配置,不再依赖 registry.conf 和 file.conf。
✅ 三、部署 Seata Server(TC)
1. 下载并解压 Seata Server
wget https://github.com/seata/seata/releases/download/v2.0.0/seata-server-2.0.0.tar.gz
tar -zxvf seata-server-2.0.0.tar.gz
2. 初始化 Seata 数据库
在 MySQL 中创建 seata 库,并执行脚本:
-- 脚本位置:seata/script/server/db/mysql.sql
CREATE DATABASE seata;
USE seata;
-- 执行 mysql.sql 创建 global_table, branch_table, lock_table
3. 配置 seata/conf/application.yml
seata:
config:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
namespace: "" # 或指定命名空间ID
username: nacos
password: nacos
data-id: seataServer.properties # 自定义配置文件名
registry:
type: nacos
nacos:
application: seata-server
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
namespace: ""
cluster: default
username: nacos
password: nacos
store:
mode: db
db:
datasource: druid
db-type: mysql
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
user: root
password: your_password
4. 在 Nacos 中添加 seataServer.properties
Data ID: seataServer.properties
Group: SEATA_GROUP
内容示例:
store.mode=db
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
store.db.user=root
store.db.password=your_password
5. 启动 Seata Server
cd seata/bin
./seata-server.sh -h 127.0.0.1 -p 8091 -m db
✅ 启动后,在 Nacos 控制台应能看到 seata-server 服务注册成功。
✅ 四、Spring Boot 微服务配置(TM / RM)
以 order-service 为例,其他服务(stock、payment)类似。
1. 添加 Maven 依赖(pom.xml)
<dependencies>
<!-- Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Nacos Discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2023.0.1.0</version>
</dependency>
<!-- Seata -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2023.0.1.0</version>
</dependency>
<!-- MySQL & MyBatis -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
</dependencies>
2. 配置 application.yml
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
seata:
enabled: true
application-id: ${spring.application.name}
tx-service-group: my_tx_group # ⚠️ 关键:必须与 vgroup-mapping 对应
data-source-proxy-mode: AT
enable-auto-data-source-proxy: false # 手动代理更可控(推荐)
registry:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
namespace: ""
username: nacos
password: nacos
config:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
namespace: ""
username: nacos
password: nacos
data-id: seataServer.properties
service:
vgroup-mapping:
my_tx_group: default # ⚠️ 必须与 tx-service-group 一致
grouplist:
default: 127.0.0.1:8091 # 兼容旧版,Seata 2.0+ 可省略(通过 Nacos 发现)
💡 enable-auto-data-source-proxy: false 表示手动创建 DataSourceProxy,避免与多数据源冲突。
3. 手动创建 DataSource 代理(关键!)
@Configuration
public class SeataDataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource")
public DruidDataSource druidDataSource() {
return new DruidDataSource();
}
@Primary
@Bean("dataSource")
public DataSource dataSource(DruidDataSource druidDataSource) {
return new DataSourceProxy(druidDataSource);
}
}
✅ 必须使用 DataSourceProxy 包装原始数据源,Seata 才能拦截 SQL 并生成 undo_log。
4. 每个微服务数据库中创建 undo_log 表
-- 每个业务库(order_db, stock_db, payment_db)都要执行
CREATE TABLE `undo_log` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`branch_id` BIGINT(20) NOT NULL,
`xid` VARCHAR(100) NOT NULL,
`context` VARCHAR(128) NOT NULL,
`rollback_info` LONGBLOB NOT NULL,
`log_status` INT(11) 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;
✅ 五、编写分布式事务代码
TM 端(订单服务)------ 发起全局事务
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping("/createOrder")
@GlobalTransactional(name = "create-order-tx", rollbackFor = Exception.class)
public String createOrder(@RequestBody OrderDTO dto) {
orderService.createOrder(dto); // 内部调用 stock-service 和 payment-service
return "success";
}
}
RM 端(库存/支付服务)------ 只需普通本地事务
@Service
public class StockService {
@Transactional
public void deductStock(Long productId, Integer count) {
// 扣减库存
stockMapper.updateStock(productId, count);
// 模拟异常:throw new RuntimeException("库存不足");
}
}
✅ RM 不需要任何 Seata 注解,只需保证方法上有 @Transactional。
✅ 六、验证与调试
- 启动顺序 :
- 启动 Nacos
- 启动 Seata Server
- 启动所有微服务
- 检查项 :
- Nacos 控制台:
seata-server和各微服务是否注册? - 数据库:各业务库是否有
undo_log表? - 日志:Seata Client 是否连接到 TC?
- Nacos 控制台:
- 测试场景 :
- 正常流程:全部提交
- 异常流程(如库存不足):全部回滚,
undo_log被清理
✅ 七、常见问题排查
| 问题 | 解决方案 |
|---|---|
no available service 'default' |
检查 tx-service-group 与 vgroup-mapping 是否一致 |
| 无法连接 Seata Server | 检查 Nacos 中 seata-server 是否在线,端口 8091 是否开放 |
undo_log 未生成 |
确认使用了 DataSourceProxy,且方法上有 @Transactional |
| Seata 2.0 配置不生效 | 放弃 registry.conf,统一使用 application.yml |
✅ 总结
通过以上步骤,你已成功在 Spring Boot 项目中集成 Seata AT 模式 + Nacos,实现强一致的分布式事务。核心要点:
- Seata Server 用 Nacos 注册 & 配置
- 客户端手动代理 DataSource
- 每个业务库建 undo_log 表
- **TM 用
@GlobalTransactional,RM 用普通 **@Transactional
📌 完整项目结构建议参考官方示例或 GitHub 开源项目(如 seata/samples)。
如需进一步优化(如高可用 TC 集群、多命名空间隔离等),可在此基础上扩展。