什么是分布式事务

核心定义
分布式事务是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的不同节点之上。简单来说,一个业务操作需要调用多个服务,这些服务使用不同的数据库,要保证这些服务的数据操作要么全部成功,要么全部失败

为什么它很复杂
在单体应用中,我们可以依赖数据库的 ACID 事务(原子性、一致性、隔离性、持久性)来保证数据一致性。但在分布式系统中,数据分散在不同的服务、不同的数据库中,传统的单数据库事务无法跨库、跨服务生效。

理论基础:CAP 和 BASE
要理解分布式事务的解决方案,必须先了解两个理论:

  1. CAP 定理:一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。

    • 一致性 (C):所有节点在同一时间看到的数据是一样的。
    • 可用性 (A):每个请求都能得到响应(不保证是最新数据)。
    • 分区容错性 (P):系统在遇到网络分区(节点之间无法通信)时仍然能继续工作。
    • 由于网络分区无法避免,分布式系统必须选择 P。因此,实际是在 CPAP 之间做权衡。
  2. BASE 理论:是对 CAP 中一致性和可用性权衡的结果,其核心思想是即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性

    • Basically Available (基本可用):系统出现故障时,允许损失部分可用性(如响应时间变长、功能降级)。
    • Soft state (软状态):允许系统存在中间状态,并且该中间状态不会影响系统整体可用性(即不同节点间数据复制存在延迟)。
    • Eventually consistent (最终一致性):经过一段时间后,所有副本的数据最终会达到一致的状态。

分布式事务方案就是在 强一致性(CP)最终一致性(AP) 之间做选择。


具体的实现方案

分布式事务的实现方案主要分为两大类:强一致性方案最终一致性方案

一、强一致性方案 (CP型)

这类方案追求数据的实时强一致性,通常会牺牲一些可用性。

  1. 两阶段提交 (2PC - Two-Phase Commit)

    • 角色:一个协调者 (Coordinator) 和多个参与者 (Participants)
    • 阶段一:准备阶段 (Prepare Phase)
      • 协调者向所有参与者发送事务内容,询问是否可以提交。
      • 参与者执行事务,写入undo和redo日志,但不提交。然后向协调者报告成功(Yes)或失败(No)。
    • 阶段二:提交/回滚阶段 (Commit/Rollback Phase)
      • 如果所有参与者都回复 Yes:协调者向所有参与者发送 Commit 命令,参与者正式提交事务,释放锁资源,并反馈结果。
      • 如果任何参与者回复 No 或超时:协调者向所有参与者发送 Rollback 命令,参与者利用undo日志回滚事务,释放锁资源。
    • 缺点
      • 同步阻塞:所有参与者在等待协调者指令时都处于阻塞状态,资源被锁定。
      • 单点问题:协调者宕机会导致整个事务卡住。
      • 数据不一致:在第二阶段,如果协调者发送部分Commit消息后宕机,会导致部分参与者提交,部分未提交,数据不一致。
  2. 三阶段提交 (3PC - Three-Phase Commit)

    • 2PC的改进版,引入了超时机制和预提交阶段来减少阻塞和单点问题。
    • 阶段一:CanCommit:协调者询问参与者是否能完成事务,不执行操作,只是一种试探。
    • 阶段二:PreCommit:如果所有参与者回复Yes,协调者发送 PreCommit 命令,参与者执行事务,写日志。
    • 阶段三:DoCommit:协调者发送 DoCommit 命令,参与者正式提交。如果此阶段参与者超时未收到指令,会自动提交(基于大概率所有节点都PreCommit成功的假设)。
    • 优点:降低了阻塞范围,解决了单点协调者宕机后参与者长期阻塞的问题。
    • 缺点:实现更复杂,并且在PreCommit后出现网络分区时,可能导致数据不一致(脑裂)。

二、最终一致性方案 (AP型)

这类方案是互联网公司更常用的方案,保证系统的可用性,通过补偿等方式达到最终一致。

  1. TCC (Try-Confirm-Cancel)

    • 核心思想:将一个业务逻辑拆分为三个操作,由业务代码实现。
    • Try 阶段尝试执行。完成所有业务检查(一致性),并预留必须的业务资源(准隔离性)。例如:检查库存、冻结库存、优惠券、余额等。
    • Confirm 阶段确认执行。真正执行业务操作,使用Try阶段预留的资源。此操作需保证幂等
    • Cancel 阶段取消执行。释放Try阶段预留的资源。此操作需保证幂等
    • 优点:灵活性高,由业务控制,可以跨数据库、跨服务实现。
    • 缺点:对代码侵入性强,需要为每个业务逻辑设计try/confirm/cancel接口,实现复杂。需要考虑网络重试、空回滚、幂等、防悬挂等问题。
  2. 基于本地消息表 (Local Message Table)

    • 核心思想:利用本地事务和消息队列来达到最终一致性。
    • 流程
      1. 在执行业务操作的数据库中,同一事务内插入一条消息到本地消息表。
      2. 有一个定时任务轮询本地消息表,将未发送的消息发送到消息队列(如RocketMQ、Kafka)。
      3. 下游服务消费消息,处理业务。处理成功后,通知消息中心(或通过ACK机制),消息中心将本地消息标记为已成功或删除。
      4. 如果消息发送失败,定时任务会不断重试。
    • 优点:方案简单,避免了2PC的长事务问题。
    • 缺点:消息表与业务表耦合,需要定时任务轮询,对数据库有一定压力。
  3. 可靠消息最终一致性(最大努力通知)

    • 这是本地消息表的一个升级版,将本地消息表独立为独立的消息服务(MQ)。RocketMQ的事务消息就是这种模式的完美实现。
    • 流程(以RocketMQ为例)
      1. 生产者发送一个 半消息(Half Message) 到MQ,此消息对消费者不可见。
      2. MQ持久化半消息后,回复生产者已接收。
      3. 生产者执行本地事务。
      4. 生产者根据本地事务执行结果,向MQ发送 CommitRollback 指令。
        • 如果Commit,半消息对消费者可见,下游服务开始消费。
        • 如果Rollback,MQ丢弃此消息。
      5. 补偿机制:如果生产者第4步没有响应(例如宕机),MQ会回调生产者的一个接口(事务回查)来查询事务状态,从而决定是Commit还是Rollback。
    • 优点:解耦彻底,性能好,数据一致性高。
    • 缺点:需要MQ支持事务消息功能(如RocketMQ)。
  4. Saga 模式

    • 核心思想:将一个长事务拆分为多个本地短事务,每个短事务都有对应的补偿动作。如果序列中的某个事务执行失败,Saga会按反向顺序依次调用前面所有已执行事务的补偿操作。
    • 实现方式
      • 协同式 (Choreography):每个服务监听其他服务的事件并决定是否执行后续操作或补偿。事件通过消息总线传递。没有中央协调器,逻辑分散在各个服务中。
      • 编排式 (Orchestration):引入一个协调器 (Orchestrator),以命令/响应的方式告诉每个参与者该执行哪个事务或补偿操作。
    • 优点:一阶段直接提交事务,无锁,性能好。适合长流程业务。
    • 缺点:补偿动作的实现难度大,要保证幂等性。在编排式中,协调器可能成为单点。

常用的方案有哪些

在实际的工业界应用中,最终一致性方案是绝对的主流,因为它们更能满足高并发、高可用的互联网场景。

方案 一致性模型 优点 缺点 适用场景
TCC 最终一致 灵活性高,粒度可控 对代码侵入性强,实现复杂 对一致性要求高,资金、交易等核心业务
RocketMQ事务消息 最终一致 性能好,解耦彻底,几乎无侵入 依赖MQ 异步场景,如积分发放、短信通知、日志记录
Saga 最终一致 一阶段提交,性能好 补偿机制难设计 长事务、业务流程复杂的系统
2PC/3PC 强一致 由数据库/中间件实现,使用简单 性能差,阻塞问题,可用性低 数据库层面支持XA协议的传统应用,内部系统

总结与选型建议

  1. 追求强一致性:除非是银行、支付等金融核心场景,否则不推荐使用2PC/3PC,因为它们对性能和可用性影响太大。可以考虑TCC,它在业务层实现了强一致性控制。
  2. 追求最终一致性(绝大多数场景)
    • 如果业务是异步的(如发短信、发积分、记录日志),RocketMQ等消息队列的事务消息首选方案,简单高效。
    • 如果业务流程非常长(如旅行预订涉及机票、酒店、租车),Saga模式非常合适。
    • 如果业务需要高度定制化的控制,且不介意代码复杂性,TCC 是很好的选择。
  3. 通用框架:目前最流行的分布式事务框架是 Seata (Simple Extensible Autonomous Transaction Architecture)。它由阿里开源,支持 AT模式(类似2PC,但对业务无侵入)、TCC模式Saga模式XA模式,是学习和落地分布式事务的优秀选择。

简单来说,先用消息队列(最终一致性)解决问题,如果不行再考虑TCC(强一致性),流程太长就用Saga。传统的2PC/3PC正在被这些更先进的方案所取代。