分布式事务解决方案:最佳实践(新手教程)
开篇:什么是分布式事务?

在传统的应用开发中,我们通常使用一个数据库来处理数据。比如用户下单、付款这些操作都在同一个数据库里完成。这种情况下,可以通过数据库的“事务”机制保证操作的原子性,即要么全部成功,要么全部失败。
但随着互联网的发展,很多系统越来越复杂,可能需要同时操作多个不同的服务或数据库。比如:
- 订单服务要减少库存
- 用户服务要扣减积分
- 支付服务要扣除余额
这三个操作如果分别来自三个不同服务(也就是微服务架构),其中一个出错,其他两个也需要回退。这时,单靠一个数据库的事务就无法解决问题了,这就是分布式事务。
本篇文章将从零基础出发,一步步带你了解并动手实现一个简单的分布式事务场景,使用目前较为流行的方案 —— Seata。
环境准备

为了运行后续的代码示例,请先准备好以下环境:
1. Java 环境
确保你安装了 JDK 1.8 或以上版本。
java -version
2. 数据库(MySQL)
你需要安装 MySQL 并创建三张表作为案例。
示例SQL:
-- 库 orders_db
CREATE DATABASE orders_db;
-- 表 order_table
USE orders_db;
CREATE TABLE order_table (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id VARCHAR(255),
product_code VARCHAR(255),
status VARCHAR(20) DEFAULT 'PENDING'
);
-- 类似地再创建库存库 inventory_db 和积分库 point_db
3. Seata Server 下载与启动
Seata 是一个开源的分布式事务中间件。
下载地址:
选择最新 release 版本下载(例如 seata-server-1.6.1.zip)。
解压后执行:
cd seata/bin
./seata-server.sh -p 8091 -m file
这会启动 Seata 的事务协调器(TC),默认监听 8091 端口。
核心概念:通俗解释分布式事务的关键点

我们用“订外卖”这个生活中的例子类比理解:
1. 微服务 = 不同的角色
- 用户下单 → “顾客”
- 商家接单 → “餐厅”
- 骑手送餐 → “骑手”
每个角色都相当于一个微服务。
2. 分布式事务的问题
就像我们不能只等一个人确认,就下订单一样 —— 如果其中有一个环节失败,整个流程也要取消。
❗问题出现:如何让多个不相干的服务共同进退,像一个事务那样一致?
3. 三大核心组件(Seata 中的概念)
- TC(Transaction Coordinator):就是我们刚才启动的 Seata Server,它是总协调人。
- TM(Transaction Manager):发起事务请求的一方(比如“下单”的那个服务)。
- RM(Resource Manager):真正执行资源操作的各个服务,如库存管理、支付服务等。
实战项目:跟着教程写一个最简单的分布式事务系统

我们将实现一个经典的下单场景:
场景需求
- 创建一张订单(order_service)
- 减少商品库存(inventory_service)
- 扣除用户积分(point_service)
任何一个失败,则全部回滚。
第一步:搭建 Spring Boot 多模块项目
建议使用 IDEA 创建一个多模块 Maven 项目,结构如下:
distributed-transaction-demo/
├── order-service
├── inventory-service
├── point-service
└── pom.xml
每个子模块都是一个独立的 Spring Boot Web 项目。
第二步:引入 Seata 客户端依赖
在每个 service 的 pom.xml 中添加 Seata starter:
<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_test_tx_group
registry:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
⚠️如果你没有 Nacos,Seata 也支持配置文件注册方式,简化起见可以暂时设为 file 模式,参考官方文档。
第三步:编写核心业务逻辑(以 order-service 为例)
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepo;
@Autowired
private InventoryClient inventoryClient; // 调用库存服务的 Feign Client
@Autowired
private PointClient pointClient; // 积分服务客户端
@GlobalTransactional
public void createOrder(String userId, String productCode) {
// 1. 插入订单
orderRepo.save(new Order(userId, productCode));
// 2. 扣库存
boolean success = inventoryClient.deduct(productCode);
if (!success) throw new RuntimeException("库存不足");
// 3. 扣积分
pointClient.reducePoints(userId, 100);
}
}
✅ 关键注解:
@GlobalTransactional是 Seata 提供的全局事务入口,它表示该方法涉及分布式事务。
第四步:模拟异常验证一致性
我们在扣积分时主动抛异常看看是否能自动回滚前面的操作:
@Override
@GlobalTransactional
public void createOrder(String userId, String productCode) {
...
pointClient.reducePoints(userId, 100);
// 故意制造错误
int i = 1 / 0;
}
运行测试后你会发现:
- 订单没插入
- 库存没减少
- 积分没扣除
✅ 说明分布式事务生效!
常见问题解答
Q1:为什么我调用其他服务要用 Feign / Dubbo?
A:在微服务中,服务之间通过网络通信交互,Spring Cloud Feign 是一种非常简便的方式进行远程调用,并自动集成到 Spring Boot 中。
Q2:Seata 的日志在哪里看?
A:Seata Server 启动时会在当前目录下的 logs 文件夹记录详细的事务日志。发生事务冲突或异常时,这里是排查的第一现场。
Q3:不用 Seata 可以吗?有其他方案吗?
A:当然可以,比如:
- TCC(Try-Confirm-Cancel):手动写补偿逻辑
- Saga:适用于长周期任务
- 消息队列最终一致性:适合异步场景
Seata 的优势在于它基于 AT 模式,对业务侵入较小,比较适合入门学习。
学习建议:下一步该怎么学?
恭喜你完成了第一个分布式事务项目!接下来的学习路径推荐如下:
🧩第一阶段:巩固基础
- 阅读 Seata 官方文档,了解各种模式的区别(AT、TCC、SAGA)
- 练习使用 TCC 模式(手动写 Cancel 方法)
- 配合 Nacos 使用 Seata + Dubbo 完整生态链
🧠第二阶段:深入原理
- 学习两阶段提交(2PC)、三阶段提交(3PC)理论
- 理解 XA 协议与 CAP 理论的关系
- 探索 RocketMQ 在事务消息中的应用
🔧第三阶段:实战进阶
- 结合 Kafka 或 RocketMQ 实现高并发下单系统
- 对比分步事务框架 LCN、ByteTCC、Himly 等的使用差异
- 学习使用 SkyWalking 监控分布式事务状态和性能瓶颈
总结
本文介绍了什么是分布式事务以及它的现实需求,并一步步教你使用 Seata 实现了一个包含订单、库存、积分三个微服务的简单案例。希望通过这篇文章,你能建立起对这一技术的理解,并开始自己的练习与探索。
记住一句话:“分布式事务的核心不是技术本身,而是对业务一致性的理解和设计。”
坚持多练,持续进步!

评论 0