分布式事务解决方案:最佳实践(新手友好教程)
开篇:为什么我们需要分布式事务?

在现代的软件开发中,尤其是互联网产品中,系统越来越复杂,数据存储也分散在多个服务里。 比如你使用一个电商网站下单的时候,可能涉及到“支付服务”、“订单服务”、“库存服务”等多个子系统。这时候,如果我们只在一个系统里操作没问题,但一旦涉及多个系统的数据修改,就可能出现一个问题:
比如用户已经付款了,结果库存没减少;或者订单生成失败,但是钱已经被扣了。
这就引出了我们今天要讲的重点——分布式事务。
什么是分布式事务?
通俗地理解:在多个系统(服务)中完成一组相关操作,并保证这些操作要么全部成功、要么全部失败,这叫分布式事务。
它就是为了解决“跨服务”的数据一致性问题。
环境准备:先搭好你的编程环境

开始写代码之前,我们要准备好基本的开发环境。以下是一个最简单的配置建议。
所需工具清单:
- Java 11 或以上版本
- Maven 构建工具
- Spring Boot 2.7+
- MySQL 数据库
- Seata(开源的分布式事务中间件)
- IntelliJ IDEA(或其他你喜欢的 IDE)
安装步骤简述:
安装 Java
- 前往 Oracle官网 或使用 OpenJDK 下载并安装
- 配置
JAVA_HOME环境变量
安装 MySQL
- 推荐使用 XAMPP 或直接下载安装包安装
- 创建数据库和用户,记下用户名和密码
安装 Seata Server
- GitHub 地址:https://github.com/seata/seata
- 下载最新的 release 版本,例如:v1.6.x
- 解压后执行启动命令:
cd seata-server/bin sh seata-server.sh -p 8091 -m db - 注意:需要提前创建数据库并导入
sql文件(见 Seata 文档说明)
IDE 安装
- 推荐使用 IntelliJ IDEA(社区版即可)
- 安装插件:Maven、Lombok、Spring Boot Helper
核心概念讲解:从头说清楚关键技术

分布式事务的核心思想是:让多个服务协调完成一次完整的业务动作,并保持一致性。 为了做到这一点,有多种技术方案可以选择。
常见的分布式事务方案有哪些?
| 方案 | 中文名称 | 特点 | 使用场景 |
|---|---|---|---|
| TCC | Try-Confirm-Cancel | 强一致、实现较复杂 | 对一致性要求高、性能要求一般的场景 |
| SAGA | 事件驱动模式 | 易实现、最终一致性 | 可接受数据短时间不一致的业务 |
| XA | 两阶段提交 | 全局锁,性能差 | 已经逐渐被替代 |
| SEATA | 阿里开源的中间件 | 支持AT、TCC、SAGA等多种模式 | 推荐新手入门首选 |
我们今天以 Seata + AT 模式 为例来学习,因为它最容易上手,且可以自动处理大部分事情。
Seata 的核心组件:
- TC(Transaction Coordinator):事务协调者,Seata Server 角色
- TM(Transaction Manager):事务管理器,通常是业务模块自己
- RM(Resource Manager):资源管理器,管理本地事务与 TC 的通信
你可以把它们想象成一场会议中的三个角色:
- TM 是主持人(主业务逻辑)
- RM 是参会人(各服务)
- TC 是会议组织者,确保所有人都统一行动(都提交或都回滚)
实战项目:用 Seata 实现一个电商订单系统

我们来做一个实际的小项目:用户下单 -> 扣减库存 -> 扣款 -> 下单成功
我们将模拟两个微服务:
- 订单服务(Order Service)
- 库存服务(Stock Service)
这两个服务分别连接各自的数据库,但我们希望他们一起参与同一个事务。
第一步:创建两个 Spring Boot 工程
使用 IntelliJ IDEA 的 Spring Initializr 功能,分别创建两个服务:
OrderService 工程结构:
order-service
├── pom.xml
└── src
└── main
├── java
│ └── com.example.order
│ ├── OrderApplication.java
│ └── controller
│ └── OrderController.java
└── resources
└── application.yml
StockService 工程结构类似:
stock-service
├── pom.xml
└── src
└── main
├── java
│ └── com.example.stock
│ ├── StockApplication.java
│ └── controller
│ └── StockController.java
└── resources
└── application.yml
第二步:添加 Seata 依赖
在两个项目的 pom.xml 文件中增加 Seata Starter 依赖:
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.6.1</version>
</dependency>
第三步:配置 Seata 客户端
在每个项目的 application.yml 中添加如下配置(注意填写正确的 IP 和 port):
seata:
enabled: true
application-id: order-service # 填当前服务名
tx-service-group: default_tx_group
service:
vgroup-mapping:
default_tx_group: default
config:
type: file
file:
name: classpath:file.conf
registry:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
group: SEATA_GROUP
data-id: seataServer.properties
第四步:初始化 Seata 的配置文件
复制 seata-server/conf/file.conf 到你的类路径下,例如:
src/main/resources/file.conf
这个配置文件定义了事务日志存储方式和数据源信息。
第五步:编写核心代码
OrderController.java 示例:
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping("/create")
@GlobalTransactional // 关键注解:开启全局事务
public String createOrder() {
try {
orderService.createOrder();
return "订单创建成功";
} catch (Exception e) {
return "订单创建失败:" + e.getMessage();
}
}
}

OrderService.java 示例:
@Service
public class OrderService {
@Autowired
private RestTemplate restTemplate;
public void createOrder() {
// 调用库存服务,扣库存
String stockResult = restTemplate.getForObject("http://localhost:8082/stocks/reduce", String.class);
if (!"success".equals(stockResult)) {
throw new RuntimeException("库存扣减失败");
}
// 模拟业务异常
// throw new RuntimeException("故意出错");
System.out.println("订单已创建");
}
}
StockController.java 示例:
@RestController
@RequestMapping("/stocks")
public class StockController {
@GetMapping("/reduce")
public String reduceStock() {
// 模拟数据库操作:库存减1
System.out.println("库存减少成功");
return "success";
}
}
第六步:运行测试
- 启动 Seata Server
- 启动两个服务(订单和库存),访问接口:
POST http://localhost:8081/orders/create
如果你在 OrderService 中手动抛出异常:
throw new RuntimeException("故意出错");
你会发现 库存没有被扣减,Seata 帮助你实现了回滚!
常见问题解答:你可能会遇到的问题都在这里
Q1:调用服务返回 connection refused 错误怎么办?
答:请检查服务是否正常启动,端口是否正确,以及是否加了
@LoadBalanced注解(如果使用 Nacos 等注册中心的话)。
Q2:报错“Branch session not found”,该怎么解决?
答:通常发生在分布式事务中断或超时,可尝试提高事务等待时间和重试机制。
Q3:如何查看事务是否成功提交?
答:可以通过 Seata 提供的 UI 控制台(官方有提供 dashboard 插件)来查看事务状态。
Q4:AT 模式适合什么业务场景?
答:适用于大多数不需要手动写补偿逻辑的业务,对开发人员友好,是目前 Seata 的推荐模式。
学习建议:接下来你可以这样继续深入
恭喜你完成了第一个分布式事务的小项目!这是个很好的开始,但还有很多值得探索的内容:
初级进阶方向:
- 理解 Seata 的 AT、TCC、SAGA 三种模式的区别
- 尝试使用 Nacos 作为注册中心和配置中心
- 深入 Seata 的 undo_log 表原理,理解它是如何进行回滚的
中高级路线:
- 学习使用 Apache RocketMQ 实现基于消息队列的事务
- 探索 Saga 模式在长流程业务中的应用
- 掌握如何在生产环境中部署 Seata 并监控其运行状态
总结
在本篇文章中,我们从零基础出发,一步步搭建了一个基于 Seata 的分布式事务项目。通过具体的代码示例,展示了多个服务之间如何协调完成一次完整的业务流程,并保证数据的一致性。
技术本身并不难,关键在于动手去写,去验证,去调试。
坚持练习,你将很快成为分布式事务领域的“实战高手”。
🎉 你现在可以自豪地说:“我懂分布式事务了!” 🎉
如有疑问欢迎留言提问,我们一起进步!

评论 0