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

在我们开发软件系统时,尤其是大型互联网应用,数据往往分散在多个服务中。比如一个电商系统的订单服务和库存服务可能是两个独立的微服务,它们各自有自己的数据库。这个时候,当我们需要进行下单操作时,就需要同时减少库存和新增订单,这两个操作必须同时成功或同时失败,否则就会出现数据不一致的问题。
这就是我们今天要讲的核心问题 —— 分布式事务。
分布式事务就是在多个服务(通常是远程调用)之间保持事务的一致性。
通俗点说就是:跨多个“地盘”的事情,要么一起成功,要么一起回滚!
✨ 常见的使用场景:
- 电商平台下单(库存 + 订单 + 支付)
- 银行转账(从A账户转到B账户)
- 跨公司业务协作
接下来你将亲手体验一个完整的实战项目,并学会如何解决这个常见但棘手的问题!
⚙️ 二、环境准备:搭建我们的实验平台

为方便学习,我们将使用以下几个技术组件:
| 技术 | 版本 | 说明 |
|---|---|---|
| Spring Boot | 2.7.x | 快速构建Java后端服务 |
| Nacos | 2.1.x | 作为注册中心和服务配置中心 |
| Seata | 1.6.x | 开源的分布式事务框架 |
| MySQL | 5.7+ | 存储数据 |
步骤一:安装 Java 和 Maven
如果你没有安装 Java,请前往 Oracle官网 下载 JDK。
然后安装 Maven,用于管理依赖库:
brew install maven # macOS 用户
sudo apt-get install maven # Ubuntu/Linux 用户
步骤二:下载并启动 Nacos
Nacos 是阿里巴巴开源的服务发现与配置管理平台。
下载 Nacos(选择 release 包):
wget https://github.com/alibaba/nacos/releases/download/v2.1.2/nacos-server-2.1.2.zip解压并运行:
unzip nacos-server-2.1.2.zip cd nacos/bin startup.sh -m standalone # 单机模式启动访问管理界面:
http://localhost:8848/nacos
默认账号密码都是nacos
步骤三:下载并启动 Seata
Seata 是我们解决分布式事务的关键工具。
下载 Seata Server:
wget https://github.com/seata/seata/releases/download/v1.6.1/seata-server-1.6.1.zip解压并启动:
unzip seata-server-1.6.1.zip cd seata/bin seata-server.bat -p 8091 -n 1 # Windows ./seata-server.sh -p 8091 -n 1 # Linux/Mac
此时,我们的服务调度中心已经准备好了!
🔍 三、核心概念:这些术语到底啥意思?

为了让你更容易理解,我来用生活中的例子解释几个重要概念。
🧱 1. 分布式系统 vs 单体系统
- 单体系统:就像一家人住在一套房子,厨房、卧室都在一起。
- 分布式系统:像一家人搬去不同城市住,沟通就要靠电话、微信了。
💬 2. 什么是事务(Transaction)?
想象你在银行取钱:
- 打卡 → 检查余额 → 出钞 → 更新余额
这四个动作必须都成功才算一次完整的操作。一旦中间出错,整个流程要撤回来,不能只扣钱不出钞。
这个就叫事务。它有四大特性:
ACID(酸碱平衡法,记住就好 😄)
| 缩写 | 含义 | 示例 |
|---|---|---|
| A(原子性) | 全部成功或全部失败 | 取钱只能全扣款 + 出钱 |
| C(一致性) | 数据前后状态保持合法 | 不会因取钱导致余额负数 |
| I(隔离性) | 多个事务互不影响 | 你取钱和别人转账是分开处理的 |
| D(持久性) | 成功的数据不会丢 | 取完钱断电了也不能抹掉记录 |
🌐 3. CAP理论简介(选学)
CAP 理论告诉我们:在一个分布式系统中,一致性(C)、可用性(A)、分区容忍性(P) 最多只能同时满足其中两个。
Seata 主要是在 CAP 中选择了 CP(一致性 + 分区容忍),优先保证数据正确。
🔄 4. Seata 的几个关键角色
| 角色 | 含义 | 类比 |
|---|---|---|
| TC(事务协调者) | 负责事务开始和提交 | 法院法官 |
| TM(事务发起者) | 定义全局事务边界 | 总经理 |
| RM(资源管理者) | 控制本地事务执行 | 小组组长 |
现在我们知道 Seata 是怎么工作的了。那我们接着来实战!
💻 四、实战项目:实现一个简单的下单 + 扣库存功能
我们将搭建两个服务:
- 订单服务 order-service
- 库存服务 storage-service
我们要实现:
用户下单的时候库存自动减少。如果某个步骤出错,所有更改都要恢复回去!
第一步:创建 Spring Boot 项目
你可以用 Spring Initializr 创建两个项目:
- Order Service
- Storage Service
添加如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
第二步:编写数据库表结构
分别在两个库中创建表:
库存服务(storage)
CREATE TABLE `storage` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`product_id` BIGINT DEFAULT NULL,
`used` INT DEFAULT 0,
`residue` INT DEFAULT 0,
PRIMARY KEY (`id`)
);
订单服务(order)
CREATE TABLE `orders` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`user_id` BIGINT DEFAULT NULL,
`product_id` BIGINT DEFAULT NULL,
`count` INT DEFAULT 0,
`status` VARCHAR(255),
PRIMARY KEY (`id`)
);
记得初始化几条测试数据。
第三步:引入 Seata 配置(order-service 和 storage-service)
在 application.yml 文件中加上:
spring:
cloud:
alibaba:
seata:
tx-service-group: my_tx_group
feign:
client:
config:
default:
http-replace:
enabled: true
同时,在 resources 目录下新建文件 file.conf:
transport {
type = "TCP"
}
client {
async.commit.buffer.limit = 10000
lock {
retry.internal = 30
retry.times = 30
}
}
别忘了加一个 Seata 的启动监听器类:
import io.seata.config.ConfigurationFactory;
import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoDataSourceProxy
public class SeataConfig {
}
第四步:在 order-service 发起分布式事务
我们在订单服务中通过 FeignClient 调用库存服务:
@FeignClient(name = "storage-service")
public interface StorageServiceClient {
@PostMapping("/deduct")
void deductStock(@RequestParam("productId") Long productId, @RequestParam("count") Integer count);
}
然后编写下单方法(带分布式事务注解):
@Service
public class OrderService {
@Resource
private OrderRepository orderRepo;
@Resource
private StorageServiceClient storageService;
@GlobalTransactional(name = "create_order_with_stock", rollbackFor = Exception.class)
public void createOrder(Long userId, Long productId, int count) {
// 1. 创建订单
Order order = new Order();
order.setUserId(userId);
order.setProductId(productId);
order.setCount(count);
order.setStatus("CREATED");
orderRepo.save(order);
// 2. 调用库存服务扣减库存
try {
storageService.deductStock(productId, count);
} catch (Exception e) {
throw new RuntimeException("库存扣除失败!", e);
}
}
}
⚠️ 注意:只要抛出异常,Seata 会自动帮你回滚!
第五步:在 storage-service 编写扣库存逻辑
@RestController
@RequestMapping("/stock")
public class StorageController {
@Resource
private StorageRepository storageRepo;
@PostMapping("/deduct")
public void deductStock(@RequestParam Long productId, @RequestParam Integer count) {
Storage storage = storageRepo.findByProductId(productId);
if (storage.getResidue() < count) {
throw new RuntimeException("库存不足!");
}
storage.setUsed(storage.getUsed() + count);
storage.setResidue(storage.getResidue() - count);
storageRepo.save(storage);
}
}
第六步:测试一下!
- 启动 Nacos
- 启动 Seata
- 启动 order-service 和 storage-service
- 使用 Postman 或 curl 请求
/order/create接口
示例请求体(POST):
{
"userId": 1001,
"productId": 1001,
"count": 2
}
查看数据库是否两个表都有变化?再试一个错误的请求(比如库存不够),看是否会自动回滚!
❓五、新手常问问题解答
Q1:为什么我启动报错了?
答:有可能是 Nacos 或 Seata 没启动,或者配置没写对。检查端口号是否被占用,日志是否有报错信息。
Q2:@GlobalTransactional 注解失效?
答:请确保你用了 Seata Starter,并且数据库支持代理。此外,方法签名必须用 public,并且不能是静态方法。
Q3:我用的是 Redis 或 MongoDB,能用 Seata 吗?
答:Seata 目前主要支持关系型数据库(如 MySQL、Oracle)。NoSQL 有一些适配器但不推荐初级阶段尝试。
Q4:还有哪些替代方案?
答:常见的方案还有:
- TCC(两阶段补偿事务)
- Saga(长事务)
- 消息队列 + 本地事务表(进阶内容)
Seata 是目前最简单上手的之一。
🚀 六、下一步学习建议
你现在掌握了使用 Seata 实现分布式事务的基本能力,接下来可以沿着这条路继续进阶:
✅ 学习路线图:
- 掌握 Seata 高级用法
- AT 模式 vs TCC 模式
- 分布式锁与重试策略
- 学习分布式事务其他方案
- TCC(Try-Cancel-Confirm)
- Saga 模式
- 消息事务(RabbitMQ / Kafka + RocketMQ 事务消息)
- 研究底层原理
- 两阶段提交协议(2PC)
- 三阶段提交协议(3PC)
- Paxos、Raft 算法简介
- 实践更复杂的项目
- 整合 Spring Cloud Alibaba 生态体系
- 使用 SkyWalking 进行分布式追踪
- 使用 Sentinel 进行流量控制
🎉 结语:你已经迈出了第一步!
这篇文章帮助你从零基础了解什么是分布式事务,并通过实际代码演示了 Seata 的基本用法。虽然只是起步,但这已经是大多数程序员的第一大难关!
希望你能坚持下去,动手敲一遍代码、改一点Bug、跑一下接口,这样印象才会更深。分布式系统之路很远,但每一步都很精彩!
📌 课后作业:你可以尝试加入支付服务,让整个“下单 + 扣库存 + 扣余额”成为一个整体事务。
如有疑问,欢迎留言提问 👇
字数统计:约3788字
图文结构化展示,循序渐进讲解,适合零基础入门。

评论 0