分布式事务解决方案:最佳实践

徐娟
2025-06-18 01:57
阅读 314

开篇:什么是分布式事务?它能帮我们做什么?

开篇:什么是分布式事务?它能帮我们做什么?

在传统的单体应用中,所有的数据库操作都发生在同一个地方,比如一个银行系统的所有数据都在一台服务器上。这种结构下,如果我们需要从一个账户扣款,再给另一个账户加钱,我们可以很容易地用**本地事务(Local Transaction)**来保证这组操作要么全部成功,要么全部失败。

但随着互联网的发展,很多系统变得越来越复杂,我们把不同的功能拆分成了多个微服务,每个微服务都有自己的数据库。这样做的好处是更灵活、更易扩展,但也带来了一个新问题:

不同数据库之间的事务如何协调,才能保证数据一致性?

这就是我们要讲的“分布式事务(Distributed Transaction)”。

举个例子:假设你在一个电商平台下单买了一本书,这个请求可能会触发下面几个操作:

  • 订单服务:创建订单
  • 库存服务:减少库存数量
  • 支付服务:扣除用户账户的钱

这三个操作分别由三个独立的服务完成,它们可能访问的是不同的数据库。如果其中有一个步骤失败了,我们必须确保其他两个也不生效,否则就会出现“钱收了但是不发货”的情况。

所以,分布式事务就是要解决跨服务、跨数据库之间的一致性问题。它就像是一场多人参与的合作任务,所有人都要统一行动,只要一人出错,就全部回滚。


环境准备:开发环境搭建指南

本教程使用的技术栈包括:

  • Java 17(或以上)
  • Spring Boot + Spring Cloud
  • Maven(项目构建)
  • Redis 和 MySQL(作为数据库演示)
  • Nacos(作为注册中心和配置中心)
  • Seata(开源分布式事务框架)

第一步:安装Java开发工具包(JDK)

请前往 https://www.oracle.com/java/technologies/javase-downloads.html 下载并安装 JDK 17 或以上版本。

第二步:安装IDE(推荐IntelliJ IDEA)

下载地址:https://www.jetbrains.com/idea/

第三步:安装Maven

可以从官网下载:https://maven.apache.org/download.cgi 安装完成后,在终端执行以下命令确认是否安装成功:

mvn -v

第四步:安装MySQL和Redis

安装MySQL

推荐使用Docker快速部署:

docker run -p 3306:3306 --name mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-d mysql:8.0

安装Redis

同样使用Docker:

docker run -p 6379:6379 --name redis \
-d redis:latest

第五步:安装Nacos Server

GitHub地址:https://github.com/alibaba/nacos/releases

下载后解压,启动方式如下(Windows):

startup.cmd -m standalone

访问 http://localhost:8848/nacos 进入控制台,默认账号密码都是 nacos/nacos。

第六步:安装Seata Server

下载地址:https://seata.io/en-us/blog/download.html

配置文件修改要点:

  • 修改 registry.conf 中的注册中心为 Nacos
  • 启动 Seata Server:
sh seata-server.sh -p 8091 -h 127.0.0.1 -m db

核心概念:轻松理解分布式事务的关键术语

核心概念:轻松理解分布式事务的关键术语

为了让大家更好地理解分布式事务,我们先来看一些关键术语,并用生活中的类比来帮助理解:

术语 生活比喻 简单解释
分布式事务 小组合作完成一个大任务 多个系统一起完成一项业务,必须同时成功或回滚
全局事务 ID(XID) 团队的任务编号 每次分布式事务有一个唯一ID,所有参与的服务都知道它是哪一个任务的一部分
TC(Transaction Coordinator) 队长、协调员 负责协调各个服务,决定事务是提交还是回滚
RM(Resource Manager) 组员 各个服务,负责本地事务操作
TM(Transaction Manager) 总负责人 发起事务,并决定最终是否提交

分布式事务的工作流程(以 Seata 为例)

  1. 用户发起下单请求(TM开始事务)
  2. 订单服务生成订单(RM1记录日志)
  3. 库存服务减少库存(RM2记录日志)
  4. 支付服务扣款(RM3记录日志)
  5. 所有服务报告状态给TC
  6. 如果都成功 → 提交事务
  7. 如果任一失败 → 所有服务回滚

实战项目:手把手做一个简单的分布式事务项目

我们将模拟一个电商系统的下单流程,包含三个服务:

  • 订单服务
  • 库存服务
  • 支付服务

所有服务使用 Seata 实现分布式事务控制。

第一步:新建Spring Boot工程(使用Maven)

创建一个父工程 distributed-transaction-demo,然后分别创建三个子模块:

  • order-service
  • inventory-service
  • payment-service

第二步:添加依赖(以订单服务为例)

order-service/pom.xml 添加:

<dependencies>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
        <version>2022.0.0.0</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.30</version>
    </dependency>
</dependencies>

其他服务类似,略去。

第三步:配置Nacos和服务注册

application.yml 中配置注册信息(以订单服务为例):

server:
  port: 8081
spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

记得在主程序加上注解:

@EnableDiscoveryClient
@SpringBootApplication
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

第四步:配置Seata

在 resources 下新建 file.confregistry.conf 文件,内容参考 Seata 官方模板。

第五步:写代码实现下单功能

我们以订单服务为主服务,调用库存和支付服务。

订单服务接口:

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @PostMapping("/create")
    public String createOrder() {
        try {
            orderService.createOrder();
            return "Order created successfully.";
        } catch (Exception e) {
            return "Failed to create order: " + e.getMessage();
        }
    }
}

订单服务业务逻辑(使用@GlobalTransactional 开启全局事务):

@Service
public class OrderService {

    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private OrderRepository orderRepository;

    @GlobalTransactional // 开启分布式事务
    public void createOrder() {
        // 1. 创建订单
        Order order = new Order("1", "book", "user1");
        orderRepository.save(order);

        // 2. 减少库存
        inventoryService.decreaseStock("book");

        // 3. 扣款
        paymentService.deductMoney("user1", 39.9);
    }
}

库存服务接口:

@RestController
@RequestMapping("/inventory")
public class InventoryController {

    @Autowired
    private InventoryService inventoryService;

    @PostMapping("/decrease")
    public String decreaseStock(@RequestParam String productId) {
        inventoryService.decreaseStock(productId);
        return "Stock decreased for product: " + productId;
    }
}

支付服务接口:

@RestController
@RequestMapping("/payment")
public class PaymentController {

    @Autowired
    private PaymentService paymentService;

    @PostMapping("/deduct")
    public String deductMoney(@RequestParam String userId, @RequestParam double amount) {
        paymentService.deductMoney(userId, amount);
        return "Deducted " + amount + " from user: " + userId;
    }
}

启动测试

启动所有服务后,访问:

POST http://localhost:8081/order/create

如果一切顺利,你会看到订单、库存和支付三个服务都完成了操作。

如果你故意让某一个服务抛出异常,整个事务会回滚,确保数据一致性。


常见问题解答:初学者常问的问题

Q1:为什么不能直接使用本地事务?

因为本地事务只能管理一个数据库连接,而分布式事务涉及多个服务、多个数据库,无法通过传统的本地事务机制来协调。

Q2:Seata 是不是必须的?有没有替代方案?

Seata 是目前最流行的开源方案之一,但它不是唯一的。常见的还有 Atomikos、TCC、Saga等。选择哪一种取决于你的业务需求和技术栈。

Q3:如果其中一个服务宕机怎么办?

这是个好问题!在真实环境中,服务可能不可用。Seata 内部有重试机制和异步补偿机制,能在一定程度上自动处理这种情况。

Q4:Seata 的性能怎么样?

引入分布式事务确实会增加一定的网络开销,但实际生产中通过优化可以接受。建议在必要时才使用,避免滥用。

Q5:学习分布式事务需要先掌握什么基础知识?

建议先了解:

  • Spring Boot 基础
  • Spring Cloud 微服务
  • REST API 和远程调用
  • 数据库事务(ACID 特性)
  • CAP 定理基础

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

恭喜你已经完成了第一个分布式事务项目的实战!

接下来你可以沿着以下几个方向继续深入:

方向一:掌握其他主流分布式事务方案

除了 Seata,你还应该了解:

  • TCC(Try-Confirm-Cancel)模式
    • 更灵活,适用于高并发场景
  • SAGA 模式
    • 适用于长时间运行的业务流程
  • 消息驱动事务(如 RocketMQ 事务消息)
    • 利用消息队列实现最终一致性

方向二:研究Seata底层原理

深入了解 Seata 的 AT 模式是如何工作的:

  • 如何自动生成 undo_log 表?
  • 如何解析 SQL 并进行反向补偿?
  • 如何与 Nacos 配合做注册发现?

方向三:结合实际业务场景优化

比如:

  • 如何做幂等设计?
  • 如何设置事务超时时间?
  • 如何做异步补偿机制?

方向四:阅读源码和文档

官方文档是最好的参考资料:


结语:坚持就是进步的动力

分布式事务是微服务架构中非常重要的一环。虽然刚开始看起来有点复杂,但只要你肯动手实践,逐步理解每一个环节,就能掌握这项核心技能。

记住一句话:

“编程没有捷径,只有不断练习和思考。”

希望这篇教程能成为你学习路上的一个坚实台阶。加油,未来的架构师!

评论 0

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