分布式事务解决方案:最佳实践(面向初学者的实战教程)

徐强△
2025-06-22 22:19
阅读 671

开篇:你为什么需要分布式事务?

开篇:你为什么需要分布式事务?

想象这样一个场景:你在网上购物,付款成功后系统提示订单创建失败了。为什么会这样?这可能是因为支付和下单是两个不同的服务,而这两个操作没能同时完成。

这就引出了我们今天要学的内容 —— 分布式事务。它解决的是在多个服务之间保证事务一致性的问题。

通俗点说,就是让你在“转账”、“下单”、“库存扣减”等多个步骤中,要么全部成功,要么全部失败,不会出现一半完成的情况。


环境准备:搭建开发环境

环境准备:搭建开发环境

我们要使用 Spring Boot + Seata 来演示分布式事务的实现。Seata 是一个开源的分布式事务解决方案,适合刚入门的学习者。

步骤 1:安装 Java JDK

确保你已安装 JDK 1.8 或以上版本。

java -version

如果没有安装,请去 Oracle官网 下载安装。

步骤 2:安装 MySQL 数据库

你可以通过以下命令安装:

sudo apt update
sudo apt install mysql-server

安装完成后,启动数据库,并新建一个名为 order 的数据库。

CREATE DATABASE order;

同样创建另一个数据库 accountstorage

步骤 3:安装并启动 Seata Server

前往 Seata 官网 下载 Seata 的压缩包(建议选稳定版本如 v1.7.0)。

解压后进入目录:

cd seata-server-1.7.0

运行 Seata:

sh ./bin/seata-server.sh

如果你用的是 Windows,可以用 PowerShell 执行 .bat 文件启动。


核心概念:几个必须理解的专业术语

核心概念:几个必须理解的专业术语

为了更好地理解分布式事务,下面这几个术语非常重要:

术语 解释
TC(Transaction Coordinator) 事务协调器,也就是 Seata Server,负责协调全局事务
TM(Transaction Manager) 事务管理器,用于开启和提交/回滚全局事务
RM(Resource Manager) 资源管理器,每个微服务就是一个 RM

简单类比一下:

  • TC 就像裁判;
  • TM 是队长,负责发起比赛(事务);
  • RM 是球员,负责执行具体动作(操作数据库)。

实战项目:实现一个简单的电商系统

我们将实现一个电商系统的三个核心服务:

  • 库存服务(Storage)
  • 订单服务(Order)
  • 账户服务(Account)

这三个服务各自有数据库,我们要让它们一起完成一个事务:下单 → 扣库存 → 扣余额,如果任何一个失败,整个操作都要回滚。

第一步:创建 Spring Boot 项目结构

你可以使用 Spring Initializr 创建项目,选择如下依赖:

  • Spring Web
  • MyBatis Framework
  • MySQL Driver

然后创建三个模块:

  • storage-service(库存服务)
  • order-service(订单服务)
  • account-service(账户服务)

第二步:引入 Seata 依赖

在每个服务的 pom.xml 中添加:

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

第三步:配置 Seata 连接信息

在每个服务的 application.yml 添加如下内容:

seata:
  enabled: true
  application-id: ${spring.application.name}
  tx-service-group: my_test_tx_group
  service:
    vgroup-mapping:
      my_test_tx_group: default
    grouplist:
      default: 127.0.0.1:8091

这里的 grouplist 指向你本地运行的 Seata Server 地址,默认端口为 8091

第四步:写一个下单接口(以 Order Service 为例)

@RestController
public class OrderController {

    @Autowired
    private OrderService orderService;

    @GetMapping("/create")
    public String createOrder() {
        try {
            orderService.create();
            return "订单创建成功";
        } catch (Exception e) {
            return "订单创建失败:" + e.getMessage();
        }
    }
}

第五步:编写带有事务注解的服务方法

@Service
public class OrderService {

    @Autowired
    private StorageClient storageClient;
    @Autowired
    private AccountClient accountClient;

    @GlobalTransactional // 关键:启用全局事务
    public void create() {
        // 1. 创建订单
        System.out.println("开始创建订单...");

        // 2. 扣库存
        storageClient.decrease(1L, 2);

        // 3. 扣余额
        accountClient.decrease(1L, 50);

        if (Math.random() > 0.5) {
            throw new RuntimeException("模拟异常");
        }
    }
}

注意:我们在代码最后加了一个随机抛异常逻辑,用来测试是否支持回滚。

第六步:其他服务也需要对应的客户端方法

比如 StorageClient 是通过 Feign 调用 Storage Service 提供的接口:

@FeignClient(name = "storage-service")
public interface StorageClient {
    @PostMapping("/decrease")
    void decrease(@RequestParam Long productId, @RequestParam Integer count);
}

对应的 Storage Service 里有一个实际操作数据库的接口。


常见问题解答

❓ Q1:分布式事务会影响性能吗?

A:会有一点影响,因为多了一层事务控制和日志记录。但如果业务需求确实需要强一致性,这是值得的。


❓ Q2:Seata 支持哪些数据库?

A:主流的数据库都支持,如 MySQL、PostgreSQL、Oracle 等。 使用时只需加上 AT 模式的自动代理即可。


❓ Q3:能否在不改代码的前提下使用 Seata?

A:不能完全无侵入,至少要在主入口加 Seata 配置,并在业务方法上加 @GlobalTransactional 注解。


❓ Q4:除了 Seata,还有哪些常见的分布式事务框架?

A:常见方案包括:

  • TCC(Try-Confirm-Cancel)
  • SAGA(事件驱动型)
  • 两阶段提交(2PC)—— 不推荐用于生产
  • 消息队列+本地事务表(适用于最终一致性)

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

掌握了 Seata 的基本使用之后,你就可以进一步深入学习以下内容:

✅ 推荐学习路径:

  1. 学习更多分布式事务模式
    • 如 TCC、SAGA、Event Sourcing 等
  2. 了解 Seata 源码实现原理
    • 有助于深入理解事务协调机制
  3. 结合消息队列使用
    • 比如 RabbitMQ 或 Kafka,提高异步处理能力
  4. 部署到真实环境中练习
    • 比如阿里云 ECS + 容器化部署

总结

本篇文章带大家从零基础了解什么是分布式事务,以及如何使用 Seata 在 Spring Boot 项目中实现它。通过实战项目,我们实现了下单流程中的三个关键操作,并验证了其事务一致性。

作为初学者,记住一句话:

“先跑通,再深入。”

希望这篇图文并茂的小白友好教程能帮助你快速上手分布式事务!


💡 小贴士:遇到问题不要怕,多查 Seata 的 GitHub Issues 和官方文档,你会发现里面有很多答案等着你!

评论 0

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