# springboot-seata-demo **Repository Path**: aiobc/springboot-seata-demo ## Basic Information - **Project Name**: springboot-seata-demo - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: seata-openfeign - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-02-26 - **Last Updated**: 2026-02-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Spring Boot + Seata 分布式事务示例 ## 项目简介 本项目是一个基于 Spring Boot 和 Seata 的分布式事务示例,用于学习和验证 Seata 在微服务架构中的分布式事务处理能力。项目模拟了一个电商场景,包含账户、订单、库存三个核心服务,通过 Seata 实现分布式事务的一致性。 ## 技术栈 - Spring Boot 2.7.18 - Seata 2.1.0 - Spring Cloud OpenFeign 服务调用框架 - Nacos 服务注册中心与配置中心 - JDBC 数据库操作 ## 项目结构 ``` springboot-seata-demo/ ├── spring-cloud-starter-alibaba-seata-adapter/ # seata的spring cloud openfeign适配器,解决org.apache.seata.seata-spring-boot-starter:2.1.0与spring cloud openfeign的兼容性问题,没有透传xid ├── springboot-seata-common/ # 公共接口定义 ├── springboot-seata-account/ # 账户服务 ├── springboot-seata-order/ # 订单服务 ├── springboot-seata-storage/ # 库存服务 ├── springboot-seata-business/ # 业务服务(事务发起方) └── pom.xml # 项目父pom ``` ![架构图](./doc/iamges/architecture-8824bcc834b3a799d58cd93dcfb6bfe2.png) ## 核心服务说明 ### 1. 公共接口模块 (springboot-seata-common) 定义了各服务间调用的接口: - `AccountService`: 账户服务接口,提供余额扣减功能 - `OrderService`: 订单服务接口,提供订单创建功能 - `StorageService`: 库存服务接口,提供库存扣减功能 ### 2. 账户服务 (springboot-seata-account) 负责用户账户余额管理: - 提供 `debit` 方法,用于扣减用户账户余额 - 参与 Seata 分布式事务 ### 3. 订单服务 (springboot-seata-order) 负责订单创建和管理: - 提供 `create` 方法,用于创建订单 - 调用账户服务扣减余额 - 参与 Seata 分布式事务 ### 4. 库存服务 (springboot-seata-storage) 负责商品库存管理: - 提供 `deduct` 方法,用于扣减商品库存 - 提供 `batchDeduct` 方法,用于批量扣减库存(测试用) - 参与 Seata 分布式事务 ### 5. 业务服务 (springboot-seata-business) 事务发起方,协调其他服务完成业务流程: - 提供 `purchaseCommit` 方法,测试事务正常提交 - 提供 `purchaseRollback` 方法,测试事务回滚 - 使用 `@GlobalTransactional` 注解开启分布式事务 ## Seata 分布式事务实现 ### 事务注解 在业务服务的方法上使用 `@GlobalTransactional` 注解开启分布式事务: ```java @GlobalTransactional(timeoutMills = 300000, name = "spring-dubbo-tx") public void purchaseCommit(String userId, String commodityCode, int orderCount) { // 业务逻辑 } ``` ### 事务传播 - 事务由业务服务发起,生成全局事务ID (XID) - XID 通过 Spring Cloud OpenFeign 调用上下文传递给其他服务 - 各服务通过 `RootContext.getXID()` 获取当前事务ID - 所有服务的数据库操作都在同一个全局事务下执行 ### 注意:Seata 与 Spring Cloud OpenFeign 集成问题 本项目在集成 Seata 2.1.0 与 Spring Cloud OpenFeign 时遇到了一个关键问题: **问题现象**:使用 `org.apache.seata:seata-spring-boot-starter:2.1.0` 依赖时,全局事务ID (XID) 无法在 OpenFeign 服务调用间正确传递,导致各服务的 `RootContext.getXID()` 返回 `null`,分布式事务失效。 **原因分析**:Seata 2.1.0 的官方 starter 包未正确适配 Spring Cloud OpenFeign 的调用上下文传递机制。 **解决方案**: 1. 本项目创建了自定义模块 `spring-cloud-starter-alibaba-seata-adapter`,该模块包含了 Spring Cloud OpenFeign 与 Seata 集成所需的适配器代码 2. 这些代码来源于 `com.alibaba.cloud:spring-cloud-starter-alibaba-seata:2021.0.5.0` 依赖,确保了与 Spring Cloud 版本的兼容性 3. 通过引入该自定义模块,解决了全局事务ID (XID) 在 OpenFeign 服务调用间的传递问题 **自定义适配器模块功能**: - `SeataFeignRequestInterceptor`:在 Feign 请求中添加 XID 头部 - `SeataHandlerInterceptor`:在 HTTP 请求中添加和获取 XID - 自动配置类:确保适配器正确初始化和使用 ### 事务回滚 - 当业务流程中发生异常时,Seata 会自动回滚所有已执行的数据库操作 - 示例中 `purchaseRollback` 方法模拟了随机异常,用于测试事务回滚 ## 数据库表结构 各服务使用独立的数据库,包含以下表: ### 账户服务 ```sql CREATE TABLE `account_tbl` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` varchar(255) DEFAULT NULL, `money` int(11) DEFAULT 0, PRIMARY KEY (`id`) ); ``` ### 订单服务 ```sql CREATE TABLE `order_tbl` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` varchar(255) DEFAULT NULL, `commodity_code` varchar(255) DEFAULT NULL, `count` int(11) DEFAULT 0, `money` int(11) DEFAULT 0, PRIMARY KEY (`id`) ); ``` ### 库存服务 ```sql CREATE TABLE `stock_tbl` ( `id` int(11) NOT NULL AUTO_INCREMENT, `commodity_code` varchar(255) DEFAULT NULL, `count` int(11) DEFAULT 0, PRIMARY KEY (`id`), UNIQUE KEY (`commodity_code`) ); ``` ## 配置说明 ### Seata 配置 在各服务的 `application.properties` 文件中配置 Seata: ```properties # Seata 应用ID seata.application-id=springboot-dubbo-seata-business # 事务服务组 seata.tx-service-group=my_test_tx_group # 启用Seata seata.enabled=true # 服务组映射 seata.service.vgroup-mapping.my_test_tx_group=default # Seata服务器地址 seata.service.grouplist.default=127.0.0.1:8091 # 注册中心类型 seata.registry.type=file # 配置中心类型 seata.config.type=file ``` ### Dubbo 配置 ```properties # Dubbo应用名 dubbo.application.name=springboot-dubbo-seata-business # 禁用QoS dubbo.application.qos-enable=false # 扫描Dubbo注解 dubbo.scan.base-packages=org.apache.seata # 注册中心地址 dubbo.registry.address=nacos://localhost:8848 # 协议名 dubbo.protocol.name=dubbo # 协议端口 dubbo.protocol.port=20883 ``` ## 运行指南 ### 环境准备 1. 启动 MySQL 数据库 2. 启动 Nacos 注册中心 (端口:8848) 3. 启动 Seata Server (端口:8091) ### 数据库初始化 执行各服务 `src/main/resources/all.sql` 文件中的SQL语句,创建数据库表并初始化测试数据。 ### 启动服务 按以下顺序启动服务: 1. springboot-seata-account 2. springboot-seata-storage 3. springboot-seata-order 4. springboot-seata-business ### 测试接口 #### 测试事务提交 ``` GET http://localhost:9991/testCommit ``` #### 测试事务回滚 ``` GET http://localhost:9991/testRollback ``` ## 事务流程说明 ### 正常流程 1. 业务服务调用库存服务扣减库存 2. 业务服务调用订单服务创建订单 3. 订单服务调用账户服务扣减余额 4. 所有操作成功,事务提交 ### 异常流程 1. 业务服务调用库存服务扣减库存 2. 业务服务调用订单服务创建订单 3. 订单服务调用账户服务扣减余额 4. 任意服务发生异常 5. Seata 回滚所有已执行的操作 ## 注意事项 1. 确保 Seata Server 已正确配置并启动 2. 确保各服务的数据库中已创建 Seata 所需的 undo_log 表 3. 确保 Nacos 注册中心正常运行 4. 各服务的 seata.tx-service-group 配置必须一致 5. 测试时可以通过修改 `purchaseRollback` 方法中的异常模拟逻辑来验证事务回滚 ## 学习资源 - [Seata 官方文档](https://seata.io/zh-cn/docs/) - [Spring Boot 官方文档](https://spring.io/projects/spring-boot) - [Dubbo 官方文档](https://dubbo.apache.org/zh/) - [Nacos 官方文档](https://nacos.io/zh-cn/docs/) ## 许可证 Apache License 2.0