分布式事务解决方案:最佳实践(面向零基础初学者)
一、开篇:分布式事务是做什么的?

你有没有遇到过这样的问题:比如你在购物网站下单,扣款成功了,但订单却没有生成?或者在银行转账时,钱被转出但没有到账?
这些问题都和“事务”有关。事务就是一系列操作要一起成功,要么一起失败。
但在现代系统中,往往数据分布在不同的服务或数据库中。例如:
- 用户服务有自己的用户表
- 订单服务有自己的订单表
- 库存服务有自己的库存记录
这个时候,如果我们要做一次“下单扣库存”的操作,就需要这三个服务之间的数据保持一致。
这就引出了一个关键的技术点:分布式事务 —— 它是用来保证跨多个服务的数据一致性的一种机制。
场景举例:
比如你要买一件衣服:
- 用户下单 → 订单服务创建订单
- 扣除库存 → 库存服务减去1件商品
- 扣除余额 → 用户账户服务扣除金额
这三项操作必须全部成功或全部失败,不能只完成其中两个。
二、环境准备:搭建开发环境

为了更好地理解分布式事务,我们使用以下技术栈进行实操:
- Java(推荐JDK 8或以上)
- Spring Boot(框架)
- MySQL(作为数据库)
- Seata(阿里开源的分布式事务中间件)
- Maven(项目依赖管理工具)
步骤1:安装JDK和IDE
你可以选择以下任意一个开发环境:
- IntelliJ IDEA(推荐新手用Ultimate版)
- Eclipse + JDK
安装步骤略过,因为不是本教程重点。
步骤2:安装MySQL
- 下载并安装 MySQL
- 创建两个测试数据库:
CREATE DATABASE order_service; CREATE DATABASE inventory_service;
步骤3:安装Seata Server
- 到 Seata官网 下载
seata-server - 解压后进入
bin目录,运行启动脚本:
(Windows用对应的seata-server.sh -p 8091 -m file.bat文件)
这样你就准备好了一个可以处理分布式事务的中间件!
三、核心概念:通俗解释关键技术
1. 什么是本地事务?
本地事务指的是在同一台服务器上的数据库事务,例如在一个数据库中对订单进行增删改查,这类事务天然支持 ACID 特性(原子性、一致性、隔离性、持久性)。
2. 分布式事务中的三大角色
| 角色 | 作用 |
|---|---|
| TC(Transaction Coordinator) | 协调者,即Seata Server,负责协调各个事务分支 |
| TM(Transaction Manager) | 事务发起方,决定全局事务的提交或回滚 |
| RM(Resource Manager) | 资源管理者,通常是各个数据库,执行本地事务 |
3. 分布式事务常用方案介绍(适合初学者)
| 方案名 | 简介 | 优点 | 缺点 |
|---|---|---|---|
| 2PC(两阶段提交) | 典型的同步阻塞型协议 | 数据强一致性 | 可靠性低、性能差 |
| TCC(Try-Confirm-Cancel) | 通过业务逻辑控制 | 性能高、灵活 | 实现复杂、需人工编写补偿逻辑 |
| Saga 模式 | 每个操作都有补偿动作 | 高性能、适用于长周期任务 | 补偿逻辑复杂,容易出错 |
| 消息队列+本地事务表 | 异步解耦方式 | 高并发 | 实现较复杂,需维护事务状态 |
| Seata(AT模式) | 自动代理数据库事务 | 对代码侵入少、易集成 | 需引入中间件 |
✅ 推荐入门学习顺序:Seata AT 模式 → TCC → Saga → 2PC
四、实战项目:用 Seata 实现一个简单订单+库存扣减场景

项目目标
实现一个“下单时扣库存”的功能,并确保这两个操作要么同时成功,要么同时失败。
1. 创建两个Spring Boot模块
我们分别创建两个Spring Boot项目:
order-service(订单服务)inventory-service(库存服务)
两个服务都会连接自己的数据库,并接入Seata。
2. 引入Seata依赖(以order-service为例)
在 pom.xml 中添加:
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.6.1</version>
</dependency>
同时,在配置文件 application.yml 中加入:
seata:
enabled: true
application-id: order-service
tx-service-group: my_tx_group
service:
vgroup-mapping:
my_tx_group: default
grouplist:
default: 127.0.0.1:8091
这个配置告诉Spring Boot,我们启用了Seata,并连接到本地运行的Seata Server。
3. 编写订单服务接口(order-service)
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private RestTemplate restTemplate;
// 开启分布式事务
@GlobalTransactional
public void placeOrder(String productId, int quantity) {
// 1. 插入订单
Order order = new Order(productId, quantity);
orderRepository.save(order);
// 2. 调用库存服务,减少库存
String url = "http://localhost:8081/inventory/deduct?productId=" + productId + "&quantity=" + quantity;
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
if (!response.getStatusCode().is2xxSuccessful()) {
throw new RuntimeException("库存扣减失败");
}
}
}
4. 编写库存服务接口(inventory-service)
@RestController
@RequestMapping("/inventory")
public class InventoryController {
@PostMapping("/deduct")
public String deductInventory(@RequestParam String productId, @RequestParam int quantity) {
// 假设这里从数据库扣除库存
boolean success = InventoryDB.deduct(productId, quantity);
if (success) {
return "OK";
} else {
return "Fail";
}
}
}

5. 测试流程
- 启动 Seata Server
- 启动
inventory-service - 启动
order-service - 调用
order-service的/placeOrder接口:curl http://localhost:8080/order/place?productId=1001&quantity=1
如果你模拟一个错误(比如库存不足),抛出异常后,你会看到订单不会插入,也不会减少库存 —— 这就是Seata的作用!
五、常见问题与解答
Q1:我启动了Seata,但是提示连接不上TC怎么办?
A:请检查Seata Server是否已启动,端口是否是 8091。查看日志是否有报错信息。
Q2:使用@GlobalTransactional注解的方法需要满足什么条件?
A:
- 必须标注在服务层方法上
- 方法必须为public
- 类必须被Spring管理(加@Component或@Service)
Q3:为什么我测试的时候事务没回滚?
A:
- 确保所有服务都正确接入Seata
- 确保抛出的是
RuntimeException - 不要在 try-catch 中吃掉异常
Q4:Seata支持哪些数据库?
A:目前支持常见的主流数据库,包括 MySQL、Oracle、PostgreSQL 等。
六、下一步学习建议
恭喜你完成了第一课!现在你已经具备了分布式事务的基础知识和初步实战能力。
下一步你可以学习的方向包括:
1. 学习其他分布式事务方案
- 理解 TCC 设计模式(手动补偿机制)
- 学习 Saga 模式的业务适用场景
- 尝试用 RabbitMQ 实现异步事务补偿
2. 深入理解 Seata 工作原理
- 查看 GlobalSession 是如何工作的
- 了解 AT 模式是如何拦截 SQL 并生成 Undo Log 的
- 学习 Seata 配置中心(如Nacos)的使用
3. 结合微服务架构深入实践
- 使用 Nacos 或 Eureka 做服务注册发现
- 使用 Feign 或 Dubbo 进行服务通信
- 整合 Redis 缓存优化查询性能
结语:分布式事务并不神秘!
很多同学一开始觉得分布式事务很高级很难,其实只要你掌握了基本的概念和常用的实践方案,它就是一个“高级一点的一致性保障手段”。
希望这篇教程帮你打开了通往分布式系统的又一扇门。继续加油,未来可期!
📌 资源链接推荐:
- Seata GitHub: https://github.com/seata/seata
- Spring Boot中文文档:https://springdoc.cn
- Seata官方文档:https://seata.io/zh-cn/docs/overview-intro/

评论 0