在 Spring Boot 项目中集成 Seata 的 TCC 模式 ,并使用 Nacos 作为注册中心和配置中心,是一个典型的微服务分布式事务解决方案。以下是完整的配置步骤与详细说明(基于 Seata 2.x + Nacos 2.2+)。
🧩 一、前置条件
-
Nacos 已启动(建议使用 standalone 模式)
sh nacos/bin/startup.sh -m standalone
-
MySQL 数据库已准备(用于 Seata Server 存储事务日志)
-
Seata Server 版本 ≥ 2.0.0
-
Spring Boot 项目使用 Spring Cloud Alibaba
🛠️ 二、Seata Server 配置(服务端)
1. 创建数据库表(Seata Server 专用)
创建名为 seata 的数据库,并执行 官方 SQL 脚本:
global_tablebranch_tablelock_table
注意:这些表仅用于 TC(事务协调器),不是业务库。
2. 配置 Nacos 中的 seataServer.properties
在 Nacos 控制台(http://localhost:8848/nacos)中:
-
Data ID :
seataServer.properties -
Group :
SEATA_GROUP -
配置内容:
事务组映射(关键!客户端 tx-service-group 必须匹配)
service.vgroupMapping.my_tcc_tx_group=default
存储模式
store.mode=db
store.lock.mode=db
store.session.mode=dbDB 配置
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://localhost:3306/seata?useUnicode=true&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai
store.db.user=root
store.db.password=123456客户端相关
client.undo.logTable=undo_log
⚠️ my_tcc_tx_group 是你在客户端配置的 tx-service-group 名称,必须一致!
3. 启动 Seata Server
修改 conf/application.yml(或使用默认,通过 Nacos 加载配置):
seata:
registry:
type: nacos
nacos:
application: seata-server
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
namespace: "" # 默认 public
cluster: default
username: nacos
password: nacos
config:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
namespace: ""
username: nacos
password: nacos
启动命令:
sh bin/seata-server.sh -h 127.0.0.1 -p 8091 -m db
✅ 启动后,在 Nacos 服务列表 中应看到 seata-server。
📦 三、Spring Boot 客户端配置(TCC 模式)
1. 添加 Maven 依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2022.0.0.0</version> <!-- 对应 Spring Boot 3.x / 2.x -->
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
注意:Seata Starter 版本需与 Seata Server 一致(如 2.0.0)。
2. 配置 application.yml
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
file-extension: properties
seata:
enabled: true
application-id: ${spring.application.name}
# 事务组名称,必须与 Nacos 中 service.vgroupMapping.xxx 的 key 匹配
tx-service-group: my_tcc_tx_group
registry:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
namespace: ""
cluster: default
username: nacos
password: nacos
config:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
namespace: ""
username: nacos
password: nacos
✅ tx-service-group: my_tcc_tx_group 必须与 Nacos 中 service.vgroupMapping.my_tcc_tx_group=default 一致。
3. 编写 TCC 接口(LocalTCC 模式)
@LocalTCC
public interface OrderTccService {
@TwoPhaseBusinessAction(
name = "createOrder",
commitMethod = "commit",
rollbackMethod = "rollback"
)
boolean prepareCreateOrder(BusinessActionContext context, String orderId, int amount);
boolean commit(BusinessActionContext context);
boolean rollback(BusinessActionContext context);
}
4. 实现 TCC 接口
@Service
public class OrderTccServiceImpl implements OrderTccService {
@Override
public boolean prepareCreateOrder(BusinessActionContext context, String orderId, int amount) {
// Try 阶段:预留资源(如冻结库存、预扣余额)
System.out.println("Try: 预留订单资源 " + orderId);
return true;
}
@Override
public boolean commit(BusinessActionContext context) {
// Confirm 阶段:确认提交
System.out.println("Confirm: 确认订单 " + context.getActionContext("orderId"));
return true;
}
@Override
public boolean rollback(BusinessActionContext context) {
// Cancel 阶段:回滚释放资源
System.out.println("Cancel: 取消订单 " + context.getActionContext("orderId"));
return true;
}
}
5. 在业务方法上启用全局事务
@RestController
public class OrderController {
@Autowired
private OrderTccService orderTccService;
@GlobalTransactional
@PostMapping("/order")
public String createOrder(@RequestParam String orderId, @RequestParam int amount) {
// 调用 TCC 接口(Try 阶段)
boolean success = orderTccService.prepareCreateOrder(null, orderId, amount);
if (!success) {
throw new RuntimeException("订单预留失败");
}
// 其他微服务调用...
return "下单成功";
}
}
✅ @GlobalTransactional 注解开启全局事务,Seata 会自动协调 TCC 的 Try/Confirm/Cancel。
🔍 四、验证与调试
-
启动成功标志(查看日志):
register TM success
register RM success -
Nacos 控制台 → 服务列表:能看到
order-service和seata-server -
模拟异常 :在业务方法中抛出异常,观察是否触发
rollback
📌 五、关键注意事项
| 项目 | 说明 |
|---|---|
tx-service-group |
客户端必须与 Nacos 中 service.vgroupMapping.xxx 的 key 一致 |
cluster |
客户端与 Server 的 cluster 必须相同(默认 default) |
| TCC 接口 | 必须加 @LocalTCC,方法参数需包含 BusinessActionContext |
| 幂等性 | Confirm 和 Cancel 方法必须幂等(可能重复调用) |
| 网络隔离 | Seata Server 的 -h 参数建议用内网 IP,避免 127.0.0.1 导致跨机器无法访问 |
✅ 总结
通过以上步骤,你已完成:
- Seata Server 注册到 Nacos
- Spring Boot 客户端通过 Nacos 发现 Seata
- 使用 TCC 模式实现分布式事务
- 全局事务由
@GlobalTransactional自动管理
💡 TCC 模式适合对一致性要求高、业务逻辑清晰的场景(如支付、库存)。若追求简单,可考虑 AT 模式(需 undo_log 表)。
如需完整示例代码,可参考 GitHub:seata-samples/tcc-sample。