分布式事务解决方案:最佳实践(零基础教程)
限流小保安
2025-06-24 14:43
阅读 399
一、开篇:什么是分布式事务?我们为什么需要它?

在开发大型系统时,比如电商平台、银行转账系统等,经常会遇到这样的问题:
用户下单购买商品的同时,还要扣减库存和账户余额。如果其中一个操作失败了该怎么办?
这时候,我们就会用到“分布式事务”来确保整个流程要么全部成功,要么全部失败,不会出现中间状态。
简单来说,分布式事务就是:在多个服务或数据库中执行一组操作,并保证这些操作的“原子性”,也就是要不全做,要不全不做。
二、环境准备:搭建我们的开发环境

本教程使用 Java + Spring Boot + Seata 实现一个简单的分布式事务示例。以下是必要的准备工作:
安装工具清单:
- JDK 1.8+
- Maven 3.6+
- IntelliJ IDEA(或其他IDE)
- MySQL 5.7+
- Seata 1.6+
步骤1:安装 MySQL 并创建数据库和表
-- 创建两个库:订单库、库存库
CREATE DATABASE order_db;
CREATE DATABASE inventory_db;
-- 使用 order_db
USE order_db;
CREATE TABLE orders (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT,
product_id BIGINT,
count INT,
status VARCHAR(20)
);
-- 使用 inventory_db
USE inventory_db;
CREATE TABLE inventory (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
product_id BIGINT,
stock INT
);
步骤2:启动 Seata Server(简化版)
- 到官网下载 Seata
- 解压后进入
conf目录,修改配置文件为支持你本地的数据库 - 启动 Seata:
cd seata-server sh startup.sh -p 8091 -m file
三、核心概念:用大白话讲清楚关键技术点
1. 分布式事务 vs 单体事务
- 单体事务:一个数据库里完成所有操作(简单好控制)
- 分布式事务:多个服务、数据库之间协调完成事务(复杂但更真实)
2. XA、TCC、SAGA、MQ 模型对比
| 模型 | 描述 | 优点 | 缺点 |
|---|---|---|---|
| XA | 强一致性方案,基于两阶段提交 | 稳定、数据准确 | 性能低,资源锁定时间长 |
| TCC | Try-Confirm-Cancel 三步机制 | 高性能 | 开发难度大,需人工补偿 |
| SAGA | 将事务拆成小步骤,失败就逆向回滚 | 可扩展性强 | 错误处理逻辑复杂 |
| MQ | 基于消息队列实现最终一致 | 异步处理、吞吐高 | 数据延迟,可能不一致 |
我们以 Seata 中的 AT 模式为例,演示最常用的一种方式。
四、实战项目:跟着我一起写一个简单的分布式事务案例
场景说明:
我们需要完成如下业务:
- 用户下订单
- 库存系统减少对应库存数量
- 如果其中一步失败,整个操作回滚(不能只下单没减库存,也不能减了库存却没下单)
技术架构图简述:
用户 -> 下单服务(order-service)
↓ 调用 ↓
库存服务(inventory-service)
我们先创建两个 Spring Boot 项目:
- order-service(订单服务)
- inventory-service(库存服务)
我们使用 Feign 进行服务调用,Seata 实现事务管理。
第1步:添加 Maven 依赖(以 order-service 为例)
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.6.1</version>
</dependency>
其他依赖略(MySQL驱动、Spring Web、MyBatis、Feign)
第2步:配置 Seata 在 application.yml 文件中
seata:
enabled: true
application-id: order-service
tx-service-group: my_test_tx_group
service:
vgroup-mapping:
my_test_tx_group: default
grouplist:
default: 127.0.0.1:8091
inventory-service 同理,只是应用ID不同。
第3步:编写 OrderController.java(订单接口)
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private OrderService orderService;
@GetMapping("/create")
public String createOrder() {
try {
orderService.createOrder();
return "订单创建成功";
} catch (Exception e) {
return "订单创建失败:" + e.getMessage();
}
}
}
第4步:编写 OrderService.java(包含远程调用库存服务)
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private InventoryServiceFeignClient inventoryClient;
@GlobalTransactional // Seata 的全局事务注解
public void createOrder() {
// 1. 创建订单
orderMapper.insertOrder(1L, 1001L, 2); // 用户ID=1,商品ID=1001,数量=2
// 2. 减少库存(远程调用)
inventoryClient.decreaseInventory(1001L, 2);
}
}
第5步:编写 InventoryServiceFeignClient.java(调用库存服务)
@FeignClient(name = "inventory-service")
public interface InventoryServiceFeignClient {
@PostMapping("/inventory/decrease")
void decreaseInventory(@RequestParam("productId") Long productId,
@RequestParam("count") int count);
}
第6步:库存服务的 Controller 和 Service 示例
@RestController
@RequestMapping("/inventory")
public class InventoryController {
@Autowired
private InventoryService inventoryService;
@PostMapping("/decrease")
public void decreaseInventory(@RequestParam Long productId, @RequestParam int count) {
inventoryService.decrease(productId, count);
}
}
@Service
public class InventoryService {
@Autowired
private InventoryMapper inventoryMapper;
public void decrease(Long productId, int count) {
inventoryMapper.updateStock(productId, count);
}
}
测试一下!
- 启动 Seata Server
- 启动两个 Spring Boot 服务
- 访问地址:http://localhost:8080/order/create
如果你看到订单被插入但库存没更新,说明事务回滚生效了!
五、常见问题答疑(FAQ)
Q1:分布式事务对性能影响大吗?
- 答:会影响一些,特别是XA模式会加锁,但多数生产环境会选择 TCC 或 Seata 的 AT 模式平衡性能与一致性。
Q2:Seata 是必须的吗?有没有替代方案?
- 答:不是必须的,也可以用 RocketMQ 事务消息、或者自研 TCC,但推荐使用成熟组件如 Seata。
Q3:代码中 @GlobalTransactional 是什么作用?
- 答:这是 Seata 提供的注解,加上它就能开启一个分布式事务,Seata 会自动帮你处理提交和回滚。
Q4:微服务调用必须用 Feign 吗?
- 答:不是的,你也可以使用 Dubbo、Ribbon、RestTemplate,只要能跨服务调用都可以结合 Seata。
六、学习建议:下一步我可以怎么学?
恭喜你完成了第一课!接下来你可以继续深入以下几个方向:
1. 学习 Seata 的更多模式(AT、TCC、Saga)
- 官方文档:https://seata.io
2. 学习 RocketMQ 实现最终一致性事务
- 结合 Kafka、RabbitMQ 等消息队列异步处理事务
3. 学习 CAP 定理和 BASE 理论
- 帮你理解分布式系统的取舍原则
4. 深入阅读源码:从官方 GitHub 上看 Seata 的源码结构
写在最后:
作为一名老师,我常常告诉初学者一句话:
“不要怕难的技术,只要你不放弃,早晚都能学会。”
分布式事务虽然看起来复杂,但只要你一步一步去动手写、去调试,它其实并没有想象中那么难。
加油吧,未来的大神!💪
📌 文章字数:约2087字
标签:区块链前端
为你推荐
暂无相关推荐

评论 0