分布式事务解决方案:最佳实践(适合零基础新手的教程)
开篇:什么是分布式事务?为什么要学它?

我们先来想象这样一个场景:
你用手机在某宝上买了一件衣服,付款后商家就安排发货。这个时候,系统内部会发生几件事:
- 钱从你的账户扣掉;
- 商家库存减少一件;
- 物流系统记录快递信息。
如果这些操作不是在同一个数据库里完成,而是分布在不同的服务中(例如支付服务、库存服务、物流服务),那么就需要一种机制,确保这三个操作要么全部成功,要么都不做。否则就会出现“钱被扣了但衣服没发”或者“衣服发了但不收钱”的尴尬情况。
这种跨多个服务/数据库的一系列操作要一起成功或一起失败的需求,就是 分布式事务 要解决的问题。
为什么你要学习它?
- 如今很多公司都在使用微服务架构,数据分散在不同服务中。
- 如果不懂分布式事务,系统容易出现数据不一致的问题。
- 这是中高级后端工程师必须掌握的核心技能之一。
环境准备:搭建开发环境

本教程将使用 Java 技术栈 + Spring Boot 框架 + Seata(一个开源分布式事务框架)来进行讲解。
所需软件列表
| 名称 | 用途 | 安装要求 |
|---|---|---|
| JDK 8 或以上 | 编译运行Java程序 | 必须安装 |
| IntelliJ IDEA | 编写和调试代码 | 推荐 |
| MySQL 5.7+ | 存储模拟数据 | 必须安装 |
| Maven | 项目依赖管理 | 必须安装 |
| Seata Server | 实现分布式事务控制 | 必须安装 |
步骤一:安装并配置Seata Server
- 前往 Seata官网 下载
seata-server。 - 解压到本地目录,进入
conf/start.sh(Linux/Mac)或start.bat(Windows)启动Seata服务。 - 默认情况下,Seata监听的是 8091端口(TC) 和 8099端口(REST)。
提示:如果你希望看到日志输出更清晰,可以在启动脚本中加入
-d参数(debug模式)。
步骤二:配置MySQL数据库
创建两个库:
order_db和stock_dbCREATE DATABASE order_db; CREATE DATABASE stock_db;在这两个库中分别创建表:
order_db: orders 表:
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id VARCHAR(255),
product_id VARCHAR(255),
status VARCHAR(255)
);
stock_db: products 表:
CREATE TABLE products (
id VARCHAR(255) PRIMARY KEY,
name VARCHAR(255),
stock INT
);
步骤三:初始化Spring Boot项目
使用 Spring Initializr 创建一个新的Spring Boot项目:
- Group:
com.example - Artifact:
distributed-demo - Dependencies:
- Spring Web
- MyBatis Framework
- MySQL Driver
然后导入IDEA,并添加 Seata Starter 依赖:
在 pom.xml 中添加:
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.6.1</version>
</dependency>
核心概念:通俗易懂地讲明白关键术语

什么是分布式事务?
- 就是“一次操作涉及多个服务”,而这些服务各自都有自己的数据库。
- 要保证这些服务要么都做,要么都不做。
举个简单的例子:
小明下单买书,系统要做的几个动作:
- 减用户积分 ✅
- 扣书籍库存 ✅
- 添加订单记录 ✅
如果中间任何一步出错,都应该回滚所有已经完成的操作,让一切回到原始状态。
分布式事务常用解决方案介绍(按难度递增)
| 方案名称 | 是否推荐 | 适用场景 | 说明 |
|---|---|---|---|
| 两阶段提交 (2PC) | ❌ 不推荐 | 简单场景 | 效率低,性能差 |
| TCC(Try-Confirm-Cancel) | ✅ 强烈推荐 | 中高并发 | 控制粒度细,适合业务复杂系统 |
| Saga 模式 | ✅ 推荐 | 长时间流程 | 支持异步任务,如审批流程 |
| 最终一致性(通过消息队列补偿) | ✅ 推荐 | 非强一致性需求 | 数据最终对得上就行 |
| Seata AT 模式 | ✅ 极力推荐 | 新项目首选 | 自动处理事务日志,对代码侵入少 |
Seata 是什么?
Seata 是阿里巴巴开源的一个分布式事务解决方案。
它支持多种模式,我们重点介绍最常用的 AT模式(Auto Transaction Mode):
AT模式的工作原理(简单理解):
- 在每个数据库操作前加锁(预处理)
- 修改完数据之后,把变更记录写进 undo_log 表
- 如果其中一个服务失败,则通过 undo_log 回滚之前的所有改动
- 成功则清理 undo_log 日志
优点:开发者几乎不需要修改业务逻辑,Seata自动帮你处理!
实战项目:编写一个分布式事务案例
我们来做一个最基础的例子:用户下单时,同时修改订单表和库存表,用 Seata 管理事务。
第一步:创建微服务模块结构
我们将构建两个微服务:
order-service:负责订单相关逻辑stock-service:负责库存相关逻辑
两个服务之间通过 Feign 调用进行通信。
第二步:添加Seata客户端配置
在两个服务的 application.yml 文件中,添加如下配置:
seata:
enabled: true
application-id: ${spring.application.name}
tx-service-group: default_tx_group
service:
vgroup-mapping:
default_tx_group: default
grouplist:
default: 127.0.0.1:8091
config:
type: file
注意:确保你本地已启动 Seata Server,默认地址为
127.0.0.1:8091。
第三步:创建两个服务接口
1. stock-service 的控制器
@RestController
@RequestMapping("/stock")
public class StockController {
@PostMapping("/reduce")
public String reduceStock(@RequestParam("productId") String productId) {
// 这里实际操作数据库,减库存
System.out.println("库存扣减完成:" + productId);
return "success";
}
}
2. order-service 的控制器
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping("/create")
@GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
public String createOrder() throws Exception {
try {
orderService.createOrder();
return "订单创建成功";
} catch (Exception e) {
throw new RuntimeException("创建订单失败");
}
}
}
注意:
@GlobalTransactional是 Seata 提供的注解,表示这个方法是一个全局事务入口。
第四步:调用库存服务(Feign Client)
@FeignClient(name = "stock-service")
public interface StockClient {
@PostMapping("/stock/reduce")
String reduceStock(@RequestParam("productId") String productId);
}
确保你的主类开启了 FeignClient 功能。
第五步:业务层实现订单创建逻辑
@Service
public class OrderService {
@Autowired
private StockClient stockClient;
@Autowired
private OrderMapper orderMapper;
public void createOrder() {
String productId = "123456";
// 1. 调用库存服务减库存
String result = stockClient.reduceStock(productId);
if (!"success".equals(result)) {
throw new RuntimeException("库存不足");
}
// 2. 插入订单记录
Orders order = new Orders();
order.setUserId("user_001");
order.setProductId(productId);
order.setStatus("paid");
orderMapper.insert(order);
}
}
第六步:测试分布式事务是否生效
你可以故意让 stockClient.reduceStock() 方法抛出异常,查看数据库中是否有插入数据。如果没有插入,说明 Seata 正确实现了回滚。
常见问题解答(FAQ)

问题 1:Seata 启动失败怎么办?
可能原因:
- 端口冲突(查看8091是否已被占用)
- 系统资源不足(内存或CPU)
解决办法:
- 更换端口号(编辑
file.conf) - 提升硬件配置或关闭其他占用资源的服务
问题 2:事务没有回滚怎么办?
检查以下几点:
- 方法是否有
@GlobalTransactional注解? - 是否在 Controller 层调用事务方法?应放在 Service 层!
- 抛出的异常是否属于
rollbackFor允许的范围?
问题 3:undo_log 表作用是什么?
这是 Seata 记录事务前后数据快照的地方。用于事务回滚时还原数据。
你无需手动维护此表,Seata 会自动处理。
问题 4:我能不能不引入第三方框架自己实现分布式事务?
理论上可以,但代价很高。
- 需要你自己实现事务协调器
- 错误处理、网络中断、重试机制都需要考虑
- 性能优化也非常复杂
建议初学者直接使用成熟的方案(如 Seata)入门。
学习建议:下一步怎么学?
恭喜你完成了第一个分布式事务实战项目!但这只是旅程的开始。
接下来你可以按照这条路径继续深入学习:
第一阶段:夯实基础
✅ 掌握 Spring Cloud Alibaba + Nacos(服务注册发现)
✅ 学习 RocketMQ(消息队列)实现最终一致性
✅ 学会使用 Redis 作为临时状态存储
第二阶段:掌握主流方案
✅ 掌握 TCC 模式的使用方式(适用于金融交易系统)
✅ 实践 Saga 模式(适用于长时间流程业务)
✅ 使用 XA 模式了解底层数据库交互方式
第三阶段:进阶与性能优化
✅ 深入源码解读 Seata 内部原理(适合面试加分)
✅ 学习如何监控和追踪事务链路(SkyWalking / Zipkin)
✅ 结合大数据场景处理海量事务数据(如电商业务秒杀)
结语:分布式事务并不难,关键是动手实践
分布式事务虽然听起来“高端大气”,但只要你动手尝试几次,结合 Seata 等成熟工具,就能轻松掌握这项关键技术。
记住一句话:最好的学习方式,就是边看文档边敲代码。
现在你已经掌握了环境搭建、基本概念、实战开发以及常见问题的处理方法。别停在这里,继续探索吧!
📚 文章总字数约:3601 字
💡 预计阅读时间:20~30分钟
🎯 学习建议:跟着步骤一步步搭建项目,不要只看不动手!
如需配套源码项目,欢迎留言评论获取 GitHub 仓库地址 👇

评论 0