当前位置: 首页 > backend >正文

[Java实战]Spring Boot整合Seata:分布式事务一致性解决方案(三十一)

[Java实战]Spring Boot整合Seata:分布式事务一致性解决方案(三十一)

引言

在微服务架构中,业务逻辑被拆分为多个独立的服务,每个服务可能拥有独立的数据库。当需要跨服务操作多个数据库时,如何保证数据的一致性成为关键挑战。Seata(Simple Extensible Autonomous Transaction Architecture)是阿里开源的分布式事务解决方案,支持AT、TCC、SAGA等多种事务模式。本文以 AT模式 为例,结合Spring Boot,讲解如何实现分布式事务的强一致性。

一、分布式事务与Seata原理
1.1 分布式事务的挑战
  • CAP理论:在分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition Tolerance)无法同时满足。
  • BASE理论:通过牺牲强一致性,实现最终一致性(Basically Available, Soft state, Eventually consistent)。
1.2 Seata的核心概念
  • TC(Transaction Coordinator):事务协调器,负责全局事务的提交或回滚。
  • TM(Transaction Manager):事务管理器,定义全局事务的边界(如@GlobalTransactional)。
  • RM(Resource Manager):资源管理器,管理分支事务的资源(如数据库连接)。
1.3 AT模式工作原理
  1. 阶段一(提交预操作)
    • TM向TC注册全局事务。
    • RM执行SQL操作,生成前置镜像(before image)和后置镜像(after image),并记录undo_log。
  2. 阶段二(提交或回滚)
    • 全局事务成功:TC异步删除undo_log。
    • 全局事务失败:TC根据undo_log反向补偿数据。
二、环境准备
2.1 依赖组件
  • Seata Server:1.5.0+
  • 注册中心:Nacos(或其他支持的服务发现组件)
  • 数据库:MySQL(需支持undo_log表)
2.2 数据库表准备

在每个业务数据库中添加 undo_log 表:

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,PRIMARY KEY (`id`),UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

三、Docker部署Nacos与Seata Server
3.1 部署Nacos

使用Docker快速启动Nacos服务:

# 拉取Nacos镜像(以2.0.3版本为例)
docker pull docker.1ms.run/nacos/nacos-server:v2.0.3# 启动Nacos容器(单机模式)
docker run -d \--name nacos-server \-p 8848:8848 \-e MODE=standalone \  # 单机模式-e JVM_XMS=256m \    # 最小内存-e JVM_XMX=256m \    # 最大内存--restart=always \docker.1ms.run/nacos/nacos-server:v2.0.3#整合执行  docker run -d --name nacos-server -p 8848:8848 -e MODE=standalone -e JVM_XMS=256m -e JVM_XMX=256m --restart=always docker.1ms.run/nacos/nacos-server:v2.0.3

验证访问:浏览器打开 http://localhost:8848/nacos,默认账号/密码:nacos/nacos

3.2 部署Seata Server

拉取Seata镜像并启动容器:

# 拉取Seata镜像(以1.5.0版本为例)
docker pull docker.1ms.run/seataio/seata-server:1.5.0# 启动Seata Server容器
docker run -d \--name seata-server \-p 8091:8091 \        # Seata TC端口-p 7091:7091 \        # Seata控制台端口(可选)-e SEATA_IP=宿主机IP \  # 需替换为实际IP(用于微服务连接)-e SEATA_CONFIG_NAME=file:/seata-server/resources/registry \--restart=always \docker.1ms.run/seataio/seata-server:1.5.0#整合一行方便执行docker run -d --name seata-server -p 8091:8091 -p 7091:7091 -e SEATA_IP=192.168.231.132 -e SEATA_CONFIG_NAME=file:/seata-server/resources/registry --restart=always docker.1ms.run/seataio/seata-server:1.5.0
3.3 Docker Compose一键部署 (可选)

创建 docker-compose.yml

version: '3'
services:nacos-server:image: nacos/nacos-server:v2.0.3ports:- "8848:8848"environment:- MODE=standalonenetworks:- seata-netseata-server:image: seataio/seata-server:1.5.0ports:- "8091:8091"- "7091:7091"environment:- SEATA_IP=宿主机IPvolumes:- ~/seata/config:/seata-server/resourcesnetworks:- seata-netdepends_on:- nacos-servernetworks:seata-net:driver: bridge

启动命令:

docker-compose up -d
3.4 关键配置挂载(可选)

若需自定义Seata配置(如注册中心),可通过挂载配置文件:

  1. 创建本地目录 ~/seata/config,放入 registry.conf
registry {type = "nacos"nacos {application = "seata-server"serverAddr = "宿主机IP:8848"  # 替换为Nacos容器IP或宿主机IPnamespace = "public"cluster = "default"}
}config {type = "nacos"nacos {serverAddr = "宿主机IP:8848"namespace = "public"group = "SEATA_GROUP"}
}
  1. 启动容器时挂载配置:
docker run -d \... \-v ~/seata/config:/seata-server/resources \seataio/seata-server:1.5.0
四、Spring Boot项目配置
4.1 修改微服务配置

application.yml 中,确保Seata和Nacos指向Docker容器地址:

seata:application-id: order-service    # 服务名tx-service-group: my_tx_group    # 事务组名(需与Seata Server配置一致)service:vgroup-mapping:my_tx_group: default         # 事务组映射到Seata集群registry:type: nacos                    # 注册中心类型nacos:server-addr: 192.168.231.132:8848namespace: publicconfig:type: nacosnacos:server-addr: 192.168.231.132:8848group: SEATA_GROUPnamespace: public
4.2 确保容器间网络互通

若微服务也在Docker中运行,建议使用自定义网络:

# 创建自定义网络
docker network create seata-net# 启动容器时加入网络
docker run -d --network seata-net --name nacos-server ... 
docker run -d --network seata-net --name seata-server ... 

此时,微服务容器可通过容器名(如 nacos-server:8848)访问Nacos和Seata。

五、业务代码与测试

业务代码(如全局事务注解 @GlobalTransactional)无需修改,与本地部署完全一致。测试步骤参考原文档,重点关注以下验证点:

  1. 服务注册验证
  • 在Nacos控制台查看 order-serviceseata-server 是否注册成功。
  1. 事务回滚验证
  • 模拟账户扣款异常,检查订单、库存数据是否回滚。
  1. 日志排查
    • 查看Seata Server容器日志:
      docker logs -f seata-server
      
六、Spring Boot整合Seata
6.1 项目结构
distributed-transaction-demo
├── order-service       # 订单服务
├── storage-service     # 库存服务
└── account-service     # 账户服务
6.2 添加依赖

在父工程或各子模块的 pom.xml 中添加依赖:

<!-- Seata Starter -->
<dependency><groupId>io.seata</groupId><artifactId>seata-spring-boot-starter</artifactId><version>1.5.0</version>
</dependency>
<!-- Nacos Discovery -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId><version>3.1.3</version> <!-- 使用与你的 Spring Cloud 版本兼容的版本 -->
</dependency>
6.3 配置Seata

application.yml 中配置Seata:

seata:application-id: order-service    # 服务名tx-service-group: my_tx_group    # 事务组名(需与Seata Server配置一致)service:vgroup-mapping:my_tx_group: default         # 事务组映射到Seata集群registry:type: nacos                    # 注册中心类型nacos:server-addr: 192.168.231.132:8848namespace: publicconfig:type: nacosnacos:server-addr: 192.168.231.132:8848group: SEATA_GROUPnamespace: public
6.5 业务代码实现

以订单服务为例,实现分布式事务:

@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate StorageFeignClient storageFeignClient;@Autowiredprivate AccountFeignClient accountFeignClient;@GlobalTransactional  // 开启全局事务public void createOrder(Order order) {// 1. 扣减库存storageFeignClient.deduct(order.getProductId(), order.getCount());// 2. 创建订单orderMapper.insert(order);// 3. 扣减账户余额accountFeignClient.deduct(order.getUserId(), order.getMoney());}
}
七、测试步骤
7.1 启动服务
  1. 启动 NacosSeata Server
  2. 依次启动 account-servicestorage-serviceorder-service
7.2 正常场景测试

使用Postman调用订单服务接口:

POST http://localhost:8080/order/create
Body:
{"userId": 1,"productId": 1,"count": 10,"money": 100
}

预期结果:订单创建成功,库存和账户余额均扣减。

7.3 异常场景测试

accountService.deduct() 方法中模拟异常:

public void deduct(Long userId, BigDecimal money) {// 模拟异常if (userId == 1) {throw new RuntimeException("账户扣款失败!");}// 正常扣款逻辑...
}

预期结果:订单未创建,库存扣减回滚,实现数据一致性。

八、常见问题与解决方案
  1. Seata Server无法连接Nacos

    • 检查Nacos地址和命名空间配置。
    • 确保Nacos中已配置 service.vgroupMapping
  2. undo_log表未生成

    • 检查数据库连接配置。
    • 确保每个业务库都执行了 undo_log.sql
  3. 事务未回滚

    • 确认方法上添加了 @GlobalTransactional
    • 检查异常是否被捕获(需抛出RuntimeException)。
九、总结

通过Seata的AT模式,Spring Boot可以轻松实现分布式事务的强一致性。核心步骤包括配置Seata Server、添加undo_log表、使用 @GlobalTransactional 注解标记全局事务。实际应用中需根据业务场景选择合适的事务模式(如TCC适用于高并发场景)。

附录
  • Seata官方文档

希望本教程对您有帮助,请点赞❤️收藏⭐关注支持!欢迎在评论区留言交流技术细节!

http://www.xdnf.cn/news/7835.html

相关文章:

  • 云祺容灾备份系统公有云备份与恢复实操-华为云
  • 【机器学习】支持向量机(SVM)
  • Suricata 3规则介绍、以及使用
  • 亚马逊AWS跑不动了?
  • 港股IPO市场火爆 没有港卡如何参与港股打新?
  • 网络爬虫(Web Crawler)详解
  • 第九届电子信息技术与计算机工程国际学术会议(EITCE 2025)
  • 使用 OpenCV 实现哈哈镜效果:让图像“扭曲起来”!
  • Node.js Express 项目现代化打包部署全指南
  • 基于亚马逊云科技构建音视频直播审核方案
  • Redis应用--缓存
  • MyBatis简单使用
  • 2025年度消费新潜力白皮书470+份汇总解读|附PDF下载
  • BAGEL-7B-MoT论文速读:统一多模态预训练的新特性
  • JUC高并发编程
  • 【笔记】快速安装Poetry
  • 138. Copy List with Random Pointer
  • Docker 镜像打包到本地
  • Android开发——不同布局的定位属性 与 通用属性
  • 大数据量查询优化:解锁SQL性能提升的关键
  • Node.js多版本安装工具NVM详细使用教程
  • VsCode开发环境之Node.js离线部署
  • JS 应用安全案例泄漏云配置接口调试代码逻辑框架漏洞自检
  • 华为鸿蒙电脑发布,折叠屏怎么选?
  • 实现动态增QuartzJob,通过自定义注解调用相应方法
  • OpenCV CUDA模块特征检测与描述------一种基于快速特征点检测和旋转不变的二进制描述符类cv::cuda::ORB
  • WPF核心类继承树结构
  • 学习路之uniapp--unipush2.0推送功能--服务端推送消息
  • Java安全-Servlet内存马
  • 基于多传感器融合的智能驾驶环境感知系统