分布式事务解决方案:最佳实践 —— 面向零基础的通俗教程

半夜部署日记
2025-06-12 14:31
阅读 477

开篇:什么是分布式事务?为什么重要?

开篇:什么是分布式事务?为什么重要?

在我们开发系统时,事务这个词经常听到。简单来说,事务就是一组操作,要么全部成功,要么全部失败。

比如你在银行转账,A账户扣款、B账户加钱这两个操作必须都完成,否则整个过程就不成立。这就是本地事务(Local Transaction)的概念,它由数据库来保证。

但问题是,现代互联网应用越来越复杂,一个功能可能涉及多个不同的服务和数据源。例如:

  • 用户下单 → 订单服务
  • 扣减库存 → 库存服务
  • 减少用户余额 → 支付服务

这些操作分布在不同的服务中,而每个服务都有自己的数据库。这种情况下,传统的单数据库事务已经无法满足需求了

这就引出了今天的主角:分布式事务(Distributed Transaction)

它的目标是:确保跨多个服务/数据库的操作要么都成功,要么都失败


环境准备:我们先搭好开发环境

环境准备:我们先搭好开发环境

我们要用的是 Spring Boot + Seata 来演示一个分布式事务的案例。

所需工具:

工具名 作用
JDK 1.8+ Java运行环境
Maven 3.x+ 项目构建工具
MySQL 5.7+ 数据库
Spring Boot 2.x+ 快速搭建微服务
Seata 1.6.x+ 实现分布式事务

安装步骤简述:

  1. 安装JDK

  2. 安装Maven

  3. 安装MySQL

    • 推荐使用 Docker 命令快速启动:
      docker run --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -d mysql:5.7
      
  4. 下载并启动 Seata Server


核心概念:用最简单的语言解释关键点

核心概念:用最简单的语言解释关键点

下面这几个词是学习分布式事务的基础,我们用生活中的例子来理解它们。

1. XA协议(两阶段提交)

想象你要组织一场线上聚会:

  • 第一阶段:你给每个人发消息:“大家准备好没?” → 每人回复“准备好了”
  • 第二阶段:你通知:“开始聚会!” → 大家开始执行

如果其中一个人说他还没准备好,你就不会发起第二阶段。

这就是XA协议的思想:所有参与者先确认是否可以执行,再统一执行。

缺点是性能较低,容易出现阻塞。


2. TCC(Try - Confirm - Cancel)

这是一个更灵活的做法,分为三步:

  • Try(尝试):先预留资源,比如扣库存前先冻结库存
  • Confirm(确认):真正执行操作,比如完成订单后扣除库存
  • Cancel(取消):如果出错就回滚,比如订单失败后解冻库存

TCC需要自己写代码实现 Try、Confirm 和 Cancel 的逻辑。


3. Saga模式

类似于流程管理。假设你有一个业务流程要执行 A -> B -> C 三个操作:

  • 如果 A 成功、B 成功、C 失败,那就执行 C'(反向操作)、B'、A'
  • 不一定完全恢复原始状态,所以也叫“补偿型事务”

适合长周期任务,比如订票、支付等。


4. 最终一致性(Eventual Consistency)

有些场景下,不要求实时一致。比如你发了一条微博,别人几秒内没看到没关系,只要最终看到了就行。

分布式事务也可以采用这种方式,通过异步消息队列定时对账的方式达到一致性。


实战项目:手把手教你做一次分布式事务演练

实战项目:手把手教你做一次分布式事务演练

我们来做一个小项目:

项目背景:

有两个服务:

  • 订单服务(order-service):创建订单
  • 库存服务(storage-service):扣减库存

两个服务都需要参与事务控制,使用 Seata 来协调。

项目结构:

demo-project
├── order-service
├── storage-service
└── common

步骤一:添加Seata依赖(以order-service为例)

<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>1.6.1</version>
</dependency>

配置 application.yml:

seata:
  enabled: true
  application-id: ${spring.application.name}
  tx-service-group: my_tx_group

步骤二:定义接口和调用关系

订单服务调用库存服务,扣减库存:

// OrderController.java
@PostMapping("/create")
public String createOrder(@RequestBody OrderDto dto) {
    try {
        orderService.createOrder(dto);
        return "下单成功";
    } catch (Exception e) {
        return "下单失败:" + e.getMessage();
    }
}
// OrderServiceImpl.java
@GlobalTransactional // 关键注解
public void createOrder(OrderDto dto) {
    // 创建订单
    orderRepository.save(dto.toOrder());
    
    // 调用库存服务
    storageFeignClient.deductStock(dto.getProductId(), dto.getCount());
}
// StorageFeignClient.java
@FeignClient(name = "storage-service")
public interface StorageFeignClient {
    @PostMapping("/deduct")
    void deductStock(@RequestParam("productId") Long productId, @RequestParam("count") int count);
}

步骤三:库存服务处理逻辑

// StorageController.java
@PostMapping("/deduct")
public void deduct(@RequestParam Long productId, @RequestParam int count) {
    storageService.deduct(productId, count);
}
// StorageServiceImpl.java
@Override
@Transactional // 本地事务即可
public void deduct(Long productId, int count) {
    Product product = productRepository.findById(productId).orElseThrow();
    if (product.getStock() < count) {
        throw new RuntimeException("库存不足");
    }
    product.setStock(product.getStock() - count);
    productRepository.save(product);
}

效果演示:

当你请求 /create 接口:

  • 如果库存充足,两个操作都会完成
  • 如果库存不足,会抛异常,Seata 自动回滚所有操作

常见问题:新手容易遇到的问题和解答

❓ Q1:不加 @GlobalTransactional 注解会怎样?

你会失去全局事务控制,各个服务各自为政,可能出现部分成功、部分失败的情况。


❓ Q2:Seata 启动报错“can not connect to services-server”

请检查 seata server 是否已启动,并查看日志中的端口是否与客户端配置一致。


❓ Q3:为什么用了 TCC 或 Saga 还不能回滚?

因为你必须手动编写对应的 Confirm 和 Cancel 方法,框架不会自动帮你生成。


❓ Q4:可以用 RabbitMQ 实现吗?

可以,属于“最终一致性”方案。不过需要额外加入消息幂等、定时对账机制等。


学习建议:下一步怎么学?

如果你刚掌握入门内容,接下来可以从以下几个方向继续深入学习:

方向 内容建议 学习材料推荐
✅ 进阶原理 熟悉 Seata 如何协调 TM、RM、TC 《Seata 官方文档》
✅ 其他模型 学习 TCC、Saga、SAGA Pro、BASE理论 《分布式事务:从理论到实战》
✅ 性能优化 处理高并发场景下的锁、冲突、重试等问题 架构师课程、大厂技术分享
✅ 结合业务 在电商、支付、物流等实际业务中模拟落地 自建小型商城练手

小结

这篇文章带你一步步了解了什么是分布式事务,为什么要用它,以及如何通过 Seata 来实现。我们还动手做了个简单的 demo。

记住一句话:

“分布式事务不是魔法,而是通过合理的架构设计和工具配合来解决多系统一致性问题。”

希望这篇教程能让你轻松入门,后续继续深造!

如需源码和更多实操练习,请留言获取配套GitHub工程链接 👇

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝