分布式事务理论基础及常见解决方案

发布于:2025-07-03 ⋅ 阅读:(60) ⋅ 点赞:(0)

在构建分布式系统时,事务一致性始终是最棘手的问题之一。为什么我们不能像传统单体应用一样,轻松实现 ACID?为什么很多系统会出现短暂不一致?要回答这些问题,我们必须先回到两个核心理论 —— CAP 理论BASE 理论

一、CAP 理论

CAP 是指:

  • C:Consistency(一致性)

  • A:Availability(可用性)

  • P:Partition Tolerance(分区容忍性)

1.1CAP 理论的含义:

CAP 理论由 Eric Brewer 在 2000 年提出,并由 Seth Gilbert 和 Nancy Lynch 在 2002 年形式化证明。

CAP 理论核心结论: 在一个分布式系统中,最多只能同时满足其中的两个,无法三者兼得。


1.2 三个属性的解释:

属性 说明
一致性(C) 所有节点访问同一份最新的数据副本。举个例子:你在上海写入了数据,北京读也必须马上看到这个数据。
可用性(A) 系统始终能返回非错误响应(不保证是最新的)。即系统“活着”,哪怕返回的是旧数据。
分区容忍性(P) 系统在发生网络分区(如节点之间通信中断)时,仍能继续运作。


CAP 示例说明:

系统设计 舍弃哪一个? 说明
CP 系统 舍弃可用性 比如 Zookeeper,为保证强一致性,部分节点挂掉后拒绝服务
AP 系统 舍弃一致性 比如 DNS 或某些 NoSQL(如 Couchbase),返回旧数据也可以,系统仍可用
CA 系统 舍弃分区容忍性 理论上不可实现,一旦发生分区,CA 就无法同时成立

二、BASE 理论:牺牲强一致性,换取高可用

CAP 理论之后,互联网企业发现必须在一致性和可用性之间作出平衡。这催生了更灵活的 BASE 理论

2.1 BASE 是什么?

BASE 是三个概念的组合:

  • Basically Available(基本可用):系统在部分节点出问题时,仍可提供核心功能。

  • Soft State(柔性状态):数据状态可以在一段时间内不一致。

  • Eventually Consistent(最终一致性):系统经过一段时间后,最终会达到一致状态。

2.2 BASE 理论 vs ACID 特性

特性 ACID(传统数据库) BASE(分布式系统)
一致性 强一致 最终一致
可用性 低(事务失败即中止) 高(允许短时不一致)
容错性
应用场景 银行转账、强事务系统 电商订单、社交网络

BASE 理论强调的是:不强求实时一致,但最终要一致,过程可不一致。

三、常见解决方案

3.1 两大核心模型

类别 模型 简述
强一致性 2PC / XA 保证所有节点要么一起成功,要么一起失败(同步阻塞)
最终一致性 本地消息表、可靠消息、TCC、SAGA 允许中间短暂不一致,最终一致(异步补偿)

3.2、常见实现方案

 3.2.1 XA 分布式事务(两阶段提交协议)

  • 标准: X/Open XA 协议

  • 步骤:

    1. prepare 阶段:所有资源预提交,锁住资源;

    2. commit 阶段:协调者通知提交或回滚。

  • 支持: MySQL、Oracle、PostgreSQL + Atomikos、Narayana、Bitronix

 示例:

Client (应用)
   |
   | Start global transaction
   |
Transaction Coordinator
   |
   |--> [Prepare] --> 数据库A:执行本地操作 → 写入undo log → 锁定数据 → 返回YES
   |
   |--> [Prepare] --> 数据库B:执行本地操作 → 写入undo log → 锁定数据 → 返回YES/NO

如果所有参与者都返回 YES,则进入第二阶段 commit;有任何一个返回 NO,则 rollback。 

优点:强一致性,有标准协议
缺点:性能差、容易阻塞、资源锁定严重、不适合高并发系统


3.2.2 TCC(Try-Confirm-Cancel)

  • 每个参与者都需实现三步:

    • Try:预留资源

    • Confirm:确认提交

    • Cancel:撤销操作

        示例(转账):

  • Try:冻结账户金额

  • Confirm:扣款并转账

  • Cancel:解冻账户

 优点:可控性强,支持业务补偿
 缺点:实现成本高,需要每个参与方支持三步操作


3.23 SAGA 模型(长事务拆分为局部事务 + 补偿)

  • 将长事务拆成多个子事务,按顺序执行

  • 若失败,则按相反顺序执行补偿(Undo)

 示例(订单流程):

  • T1:创建订单

  • T2:扣库存

  • T3:扣余额
    → 若 T3 失败,执行:

  • C3:退余额

  • C2:加库存

  • C1:取消订单

 优点:事务粒度小,适合长流程
 缺点:需要写补偿逻辑,最终一致性非强一致

 框架:Apache ServiceComb Pack、Seata Saga 模式


3.2.4 本地消息表 + 轮询(事务消息)

  • 在本地数据库记录消息日志(和业务操作放在一个事务中)

  • 后台线程异步扫描并发送 MQ 消息

  • 消费端处理完成后回调确认

 示例:

  • 插入订单记录 + 插入消息日志(一个事务)

  • 轮询线程异步发消息到 MQ(如 RabbitMQ、RocketMQ)

 优点:实现简单、可靠性高
 缺点:开发麻烦,依赖轮询,实时性差


 5. 可靠消息服务(事务消息队列)

  • 使用支持事务消息的 MQ(如 RocketMQ、RabbitMQ + outbox pattern)

  • 消息发送成功后,消费者处理并确认

 RocketMQ 示例(半消息):

  1. 发送“准备状态”消息(消息暂不投递)

  2. 本地业务执行成功

  3. 提交消息,才会正式投递

 优点:可靠、高性能
 缺点:依赖 MQ,MQ 挂了就影响事务

3.3 怎么取舍

  1. 需求驱动设计

    • 金融、交易类业务 → 选择强一致性(CAP 中偏 CP,牺牲可用性)

    • 电商、内容系统 → 选择最终一致性(CAP 中偏 AP,牺牲强一致性)

  2. 读写比分析

    • 如果读远多于写,可以采用多副本延迟一致性,提高可用性。

  3. 系统容错机制

    • 借助消息队列、补偿机制等设计,构建“柔性事务”,提升系统韧性。


网站公告

今日签到

点亮在社区的每一天
去签到