在微服务架构中,业务被拆分至多个独立服务,每个服务拥有专属数据源。当一笔业务跨多个服务操作数据时(如电商下单需联动订单、库存、支付服务),传统本地事务无法保证跨服务数据一致性,分布式事务问题随之凸显。Nacos 作为阿里开源的服务注册与配置中心,能提供高效的服务发现与动态配置能力;Seata 则是轻量级分布式事务框架,专注于微服务场景下的事务一致性保障。二者整合可构建稳定、易用的分布式事务解决方案,本文将从原理、实战、优化三方面完整拆解整合过程。
一、核心组件与协同原理
1.1 关键组件职责
整合方案中,Nacos 与 Seata 各司其职,同时通过协同机制实现事务闭环:
-
Nacos:承担双重角色——作为服务注册中心,让 Seata Server 与微服务实例实现动态发现;作为配置中心,统一管理 Seata 的全局配置(如事务组、集群映射等),避免分散配置导致的不一致问题。
-
Seata:通过三大核心角色实现分布式事务管控,分别是事务协调者(TC,部署在 Seata Server 中)、事务管理者(TM,嵌入业务服务,发起全局事务)、资源管理者(RM,嵌入业务服务,管理本地事务资源并响应 TC 指令)。
1.2 协同工作流程
以 Seata 主流的 AT 模式(自动事务模式,平衡易用性与性能)为例,Nacos 与 Seata 的协同流程如下:
TM 发起全局事务,向 TC 注册全局事务并获取全局事务 ID(XID);
微服务通过 Nacos 发现 Seata Server 地址,将 XID 传递至各个分支服务;
各分支服务的 RM 向 TC 注册分支事务,执行本地业务逻辑并记录回滚日志(Undo Log),完成第一阶段提交;
TC 汇总所有分支事务状态,若全部成功则下达全局提交指令,各 RM 删除回滚日志;若存在失败则下达回滚指令,各 RM 基于 Undo Log 执行回滚;
Nacos 实时同步 Seata 配置变更,确保集群节点配置一致,保障事务协调稳定性。
1.3 Seata 模式选型建议
Seata 提供多种事务模式,需结合业务场景选型:
-
AT 模式:默认模式,对业务无侵入,通过 Undo Log 实现自动回滚,适合大多数微服务场景(如电商订单、库存联动);
-
TCC 模式:需手动实现 Try、Confirm、Cancel 接口,一致性强,适合金融级核心业务(如支付结算);
-
SAGA 模式:基于状态机实现长事务拆分,适合跨服务多步骤的长事务场景(如物流调度);
-
XA 模式:依赖数据库原生事务支持,强一致性但性能较差,极少在高并发场景使用。
本文实战部分将采用 AT 模式,兼顾开发效率与业务适配性。
二、环境准备与整合实战
本次实战基于 Spring Boot 2.7.x + MyBatis-Plus 3.5.x + Seata 1.7.1 + MySQL 8.0 技术栈,以“订单创建 + 库存扣减”经典场景为例,实现分布式事务管控。
2.1 前置环境部署
Nacos Server 部署:下载 Nacos 1.4.0+ 版本(建议与 Seata 版本兼容),解压后启动单机版,访问 http://127.0.0.1:8848/nacos 验证是否正常运行,默认账号密码为 nacos/nacos。
Seata Server 部署与 Nacos 注册:
-
下载 Seata 1.7.1 版本,解压后修改conf/application.yml,配置数据源(存储全局事务状态)与 Nacos 注册中心;
-
核心配置如下(重点关注 registry 与 store 节点):
seata: registry: type: nacos # 注册中心类型为 Nacos nacos: server-addr: 127.0.0.1:8848 group: SEATA_GROUP # 需与客户端一致 application: seata-server # 注册到 Nacos 的服务名 config: type: nacos # 配置中心类型为 Nacos nacos: server-addr: 127.0.0.1:8848 group: SEATA_GROUP store: mode: db # 全局事务状态存储方式为数据库 db: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/seata?useSSL=false&serverTimezone=Asia/Shanghai user: root password: 123456 -
初始化 Seata 数据库:创建 seata 数据库,执行官网提供的建表语句,生成 global_table(全局事务表)、branch_table(分支事务表)、lock_table(全局锁表)等核心表,用于存储事务元数据。
-
启动 Seata Server:执行解压目录下的 bin/seata-server.bat(Windows)或 bin/seata-server.sh(Linux),启动后可在 Nacos 控制台“服务列表”中看到 seata-server 实例,说明注册成功。
2.2 微服务整合配置
分别搭建订单服务(order-service)与库存服务(stock-service),完成与 Nacos、Seata 的整合配置。
2.2.1 引入核心依赖
两个服务的 pom.xml 均需引入 Seata、Nacos、数据源相关依赖,核心依赖如下:
<!– Seata 核心依赖 –>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.7.1</version>
</dependency>
<!– Seata 数据源代理(AT 模式必需) –>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-datasource-proxy-druid</artifactId>
<version>1.7.1</version>
</dependency>
<!– Nacos 服务注册发现 –>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.0.5.0</version>
</dependency>
<!– 德鲁伊连接池 + MyBatis-Plus –>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
2.2.2 配置文件编写
以订单服务为例,application.yml 配置如下,库存服务仅需修改应用名与数据源地址,核心配置保持一致:
spring:
application:
name: order–service # 库存服务为 stock-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # Nacos 地址
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/order_db?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
type: com.alibaba.druid.pool.DruidDataSource
# Seata 核心配置
seata:
enabled: true
tx-service-group: my_test_tx_group # 事务组名称,需与 Seata Server 一致
service:
vgroup-mapping:
my_test_tx_group: default # 事务组与集群映射
grouplist:
default: 127.0.0.1:8091 # Seata Server 地址(默认端口 8091)
data-source-proxy-mode: AT # 启用 AT 模式数据源代理
registry:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
group: SEATA_GROUP # 与 Seata Server 注册分组一致
# MyBatis-Plus 配置
mybatis-plus:
mapper-locations: classpath:mapper/**/*.xml
type-aliases-package: com.example.order.entity
2.3 业务代码实现
基于 AT 模式实现“创建订单 + 扣减库存”逻辑,核心是通过@GlobalTransactional 注解标记全局事务发起者。
2.3.1 库存服务接口
库存服务提供扣减库存接口,作为分支事务:
@Service
public class StockServiceImpl implements StockService {
@Autowired
private StockMapper stockMapper;
@Override
public boolean deductStock(Long productId, Integer count) {
// 扣减库存逻辑
Stock stock = stockMapper.selectById(productId);
if (stock == null || stock.getCount() < count) {
throw new RuntimeException("库存不足");
}
stock.setCount(stock.getCount() – count);
return stockMapper.updateById(stock) > 0;
}
}
2.3.2 订单服务接口(全局事务发起者)
订单服务调用库存服务,通过 @GlobalTransactional 开启全局事务,确保订单创建与库存扣减要么同时成功,要么同时回滚:
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private RestTemplate restTemplate;
@Override
@GlobalTransactional(name = "createOrderTx", rollbackFor = Exception.class)
public Order createOrder(Long userId, Long productId, Integer count) {
// 1. 创建订单(本地事务)
Order order = new Order();
order.setUserId(userId);
order.setProductId(productId);
order.setCount(count);
order.setStatus(0); // 0-待支付
orderMapper.insert(order);
// 2. 调用库存服务扣减库存(远程分支事务)
boolean deductResult = restTemplate.postForObject(
"http://stock-service/stock/deduct",
new StockDeductDTO(productId, count),
Boolean.class
);
if (!deductResult) {
throw new RuntimeException("库存扣减失败");
}
return order;
}
}
2.3.3 回滚日志表创建
AT 模式需在每个业务数据库(order_db、stock_db)中创建 undo_log 表,用于存储回滚日志,建表语句如下:
CREATE TABLE IF NOT EXISTS `undo_log` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
`branch_id` BIGINT NOT NULL COMMENT '分支事务ID',
`xid` VARCHAR(128) NOT NULL COMMENT '全局事务ID',
`context` VARCHAR(128) NOT NULL COMMENT '上下文信息',
`rollback_info` LONGBLOB NOT NULL COMMENT '回滚信息',
`log_status` INT NOT NULL COMMENT '日志状态',
`log_created` DATETIME NOT NULL COMMENT '创建时间',
`log_modified` DATETIME NOT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = 'AT模式回滚日志表';
三、功能测试与问题排查
3.1 正常场景测试
调用订单服务创建订单接口,传入合法参数(库存充足),观察到:订单表新增记录,库存表对应商品库存扣减,Nacos 中 Seata 服务正常,全局事务状态为提交。
3.2 异常场景测试
模拟库存不足场景,调用接口后抛出异常:订单表未新增记录(本地事务回滚),库存表数据无变化(分支事务回滚),undo_log 表临时记录被删除,验证分布式事务回滚机制生效。
3.3 常见问题排查
-
Seata 服务无法注册到 Nacos:检查 Seata Server 与客户端的 group、namespace 是否一致,Nacos 地址是否可访问,防火墙是否开放 8848、8091 端口。
-
AT 模式回滚失败:确认业务数据库是否创建 undo_log 表,Seata 数据源代理是否启用(data-source-proxy-mode 配置为 AT),业务 SQL 是否支持幂等性。
-
全局事务 ID 传递失败:确保微服务间调用时携带 XID 上下文,Spring Cloud 环境下可通过 Seata 自动拦截器实现,无需手动传递。
四、生产环境优化建议
配置中心优化:将 Seata 客户端配置统一迁移至 Nacos 配置中心,通过 dataId 区分不同环境(如 seata-dev.yaml、seata-prod.yaml),实现动态配置更新,避免重启服务。
Seata Server 集群部署:生产环境需部署 Seata Server 集群,通过 Nacos 实现负载均衡,避免单点故障,同时将事务元数据存储切换为 MySQL 主从或 Redis 集群,提升可靠性。
性能优化:AT 模式下,undo_log 表可添加索引优化查询效率;避免长事务占用全局锁,拆分大事务为多个小事务;合理设置事务超时时间,防止资源泄露。
监控告警:集成 Seata 监控面板,实时监控全局事务成功率、回滚率等指标;通过 Nacos 健康检查机制,及时发现 Seata Server 或微服务实例异常,配置告警通知。
五、总结
Nacos 与 Seata 的整合,既借助 Nacos 实现了服务的动态发现与配置统一,又通过 Seata 简化了分布式事务的开发成本,尤其 AT 模式几乎无需侵入业务代码,即可实现跨服务数据一致性保障。本文通过经典电商场景,完整呈现了从环境部署、配置整合到业务实现的全流程,同时提供了生产环境优化方案,可为微服务架构下的分布式事务问题提供可落地的解决方案。
后续可进一步探索 Seata TCC 模式与 Nacos 的整合的适配场景,以及结合 Sentinel 实现流量控制与事务熔断的联动方案,构建更健壮的微服务体系。
网硕互联帮助中心



评论前必须登录!
注册