分布式事务

分布式事务理论基础:CAP、BASE

CAP

也就是 Consistency(一致性)Availability(可用性)Partition Tolerance(分区容错性) 这三个单词首字母组合。CAP 定理(CAP theorem)指出对于一个分布式系统来说,当设计读写操作时,只能能同时满足以下三点中的两个

  • 一致性(Consistence) : 所有节点访问同一份最新的数据副本

  • 可用性(Availability): 非故障的节点在合理的时间内返回合理的响应(不是错误或者超时的响应)

  • 分区容错性(Partition tolerance) : 分布式系统出现网络分区的时候,仍然能够对外提供服务

    什么是网络分区?

    分布式系统中,多个节点之前的网络本来是连通的,但是因为某些故障(比如部分节点网络出了问题)某些节点之间不连通了,整个网络就分成了几块区域,这就叫网络分区。

不是所谓的“3 选 2”

大部分人解释这一定律时,常常简单的表述为:“一致性、可用性、分区容忍性三者你只能同时达到其中两个,不可能同时达到”。实际上这是一个非常具有误导性质的说法,而且在 CAP 理论诞生 12 年之后,CAP 之父也在 2012 年重写了之前的论文。

当发生网络分区的时候,如果我们要继续服务,那么强一致性和可用性只能 2 选 1。也就是说当网络分区之后 P 是前提,决定了 P 之后才有 C 和 A 的选择。也就是说分区容错性(Partition tolerance)我们是必须要实现的。

简而言之就是:CAP 理论中分区容错性 P 是一定要满足的,在此基础上,只能满足可用性 A 或者一致性 C。

因此,分布式系统理论上不可能选择 CA 架构,只能选择 CP 或者 AP 架构。

为啥无同时保证 CA 呢?

举个例子:若系统出现“分区”,系统中的某个节点在进行写操作。为了保证 C, 必须要禁止其他节点的读写操作,这就和 A 发生冲突了。如果为了保证 A,其他节点的读写操作正常的话,那就和 C 发生冲突了。

在系统发生“分区”的情况下,CAP 理论只能满足 CP 或者 AP。要注意的是,这里的前提是系统发生了“分区”

如果系统没有发生“分区”的话,节点间的网络连接通信正常的话,也就不存在 P 了。这个时候,我们就可以同时保证 C 和 A 了。

总结:如果系统发生“分区”,我们要考虑选择 CP 还是 AP。如果系统没有发生“分区”的话,我们要思考如何保证 CA 。

BASE

简介

BASEBasically Available(基本可用)Soft-state(软状态)Eventually Consistent(最终一致性) 三个短语的缩写。BASE 理论是对 CAP 中一致性 C 和可用性 A 权衡的结果,其来源于对大规模互联网系统分布式实践的总结,是基于 CAP 定理逐步演化而来的,它大大降低了我们对系统的要求。

BASE 理论的核心思想

即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。

也就是牺牲数据的强一致性来满足系统的高可用性,系统中一部分数据不可用或者不一致时,仍需要保持系统整体“主要可用”。

BASE 理论本质上是对 CAP 的延伸和补充,更具体地说,是对 CAP 中 AP 方案的一个补充。

为什么这样说呢?

CAP 理论这节我们也说过了:

如果系统没有发生“分区”的话,节点间的网络连接通信正常的话,也就不存在 P 了。这个时候,我们就可以同时保证 C 和 A 了。因此,如果系统发生“分区”,我们要考虑选择 CP 还是 AP。如果系统没有发生“分区”的话,我们要思考如何保证 CA 。

因此,AP 方案只是在系统发生分区的时候放弃一致性,而不是永远放弃一致性。在分区故障恢复后,系统应该达到最终一致性。这一点其实就是 BASE 理论延伸的地方。

image-20250507152320203

  1. 基本可用

基本可用是指分布式系统在出现不可预知故障的时候,允许损失部分可用性。但是,这绝不等价于系统不可用。
什么叫允许损失部分可用性呢?
• 响应时间上的损失: 正常情况下,处理用户请求需要 0.5s 返回结果,但是由于系统出现故障,处理用户请求的时间变为 3 s。
• 系统功能上的损失:正常情况下,用户可以使用系统的全部功能,但是由于系统访问量突然剧增,系统的部分非核心功能无法使用。
2. ##### 软状态

软状态指允许系统中的数据存在中间状态(CAP 理论中的数据不一致),并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时。
3. ##### 最终一致性

最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性。

分布式事务解决方案

2PC

2PC(Two-Phase Commit)这三个字母的含义:

2 -> 指代事务提交的 2 个阶段

P-> Prepare (准备阶段)

C ->Commit(提交阶段)

2PC 将事务的提交过程分为 2 个阶段:准备阶段提交阶段准备阶段(Prepare)

准备阶段的核心是“询问”事务参与者执行本地数据库事务操作是否成功。

准备阶段的工作流程:

  1. 事务协调者**/管理者(后文简称 TM)** 向所有涉及到的 事务参与者(后文简称 RM****) 发送消息询

问:“你是否可以执行事务操作呢?”,并等待其答复。

  1. RM 接收到消息之后,开始执行本地数据库事务预操作比如写 redo log/undo log 日志,此时并不

会提交事务

  1. RM 如果执行本地数据库事务操作成功,那就回复“Yes”表示我已就绪,否则就回复“No”表示我未就

绪。

提交阶段(Commit)

提交阶段的核心是“询问”事务参与者提交本地事务是否成功。

当所有事务参与者都是“就绪”状态的话:

  1. TM 向所有参与者发送消息:“你们可以提交事务啦!”(Commit 消息
  2. RM 接收到 Commit 消息 后执行 提交本地数据库事务 操作,执行完成之后 释放整个事务期间所

占用的资源

  1. RM 回复:“事务已经提交” (ACK 消息)。
  2. TM 收到所有 事务参与者ACK 消息 之后,整个分布式事务过程正式结束。

3PC

3PC 是人们在 2PC 的基础上做了一些优化得到的。3PC 把 2PC 中的准备阶段做了进一步细化,分为 2 个阶段:

准备阶段

这一步不会执行事务操作,只是向 RM 发送 准备请求 ,顺便询问一些信息比如事务参与者能否执行本地

数据库事务操作。RM 回复“Yes”、“No”或者直接超时。

如果任一 RM 回复“No”或者直接超时的话,就中断事务(向所有参与者发送“Abort”消息),否则进入

预提交阶段

TM 向所有涉及到的 RM 发送 预提交请求 ,RM 回复“Yes”、“No”(最后的反悔机会)或者直接超时。

如果任一 RM 回复“No”或者直接超时的话,就中断事务(向所有事务参与者发送“abort”消息),否则进入执行事务提交阶段

当所有 RM 都返回“Yes”之后, RM 才会执行本地数据库事务预操作比如写 redo log/undo log 日志。

执行事务提交阶段(DoCommit

执行事务提交(DoCommit 阶段就开始进行真正的事务提交。

TM 向所有涉及到的 RM 发送 执行事务提交请求 ,RM 收到消息后开始正式提交事务,并在完成事务提

交后释放占用的资源。

如果 TM 收到所有 RM 正确提交事务的消息的话,表示事务正常完成。如果任一 RM 没有正确提交事务

或者超时的话,就中断事务,TM 向所有 RM 发送“Abort”消息。RM 接收到 Abort 请求后,执行本地数

据库事务回滚,后面的步骤就和 2PC 中的类似了。

TCC

简单来说,TCC 是 Try、Confirm、Cancel 三个词的缩写,它分为三个阶段:

  1. Try(尝试)阶段** : 尝试执行。完成业务检查,并预留好必需的业务资源。
  2. Confirm(确认)阶段** :确认执行。当所有事务参与者的 Try 阶段执行成功就会执行 Confirm ,

Confirm 阶段会处理 Try 阶段预留的业务资源。否则,就会执行 Cancel 。

  1. Cancel(取消)阶段** :取消执行,释放 Try 阶段预留的业务资源。

每个阶段由业务代码控制,这样可以避免长事务,性能更好。

我们拿转账场景来说:

  1. Try(尝试)阶段** : 在转账场景下,Try 要做的事情是就是检查账户余额是否充足,预留的资源就是

转账资金。

  1. Confirm(确认)阶段** : 如果 Try 阶段执行成功的话,Confirm 阶段就会执行真正的扣钱操作。
  2. Cancel(取消)阶段** :释放 Try 阶段预留的转账资金。

一般情况下,当我们使用 TCC 模式的时候,需要自己实现 try , confirm , cancel 这三个方法,来达到

最终一致性。

问题:
空回滚

空回滚指的是,当分支事务的try阶段阻塞,引起全局事务回滚时,有的分支事务可能并未执行try操作,但却执行了cancel操作,所以需要空回滚

业务悬挂

业务悬挂指的是,当空回滚发生后,如果后续继续执行try操作,但由于已经回滚过了,就不能再发生回滚了。所以应该阻止业务悬挂这种情况

SAGA

  • 依赖本地事务:每个 Saga 参与者(如订单服务、库存服务)的本地操作都是一个独立的本地事务,执行后立即提交。
  • 补偿触发机制:若后续步骤失败,需通过逆向事务(Compensating Transaction)回滚已提交的操作。

Seata

seata主要包含XA,AT,TCC三种模式,其中XA和AT都属于2PC的变体,AT在执行每个独立事务的时候会直接提交,如果出错再通过undolog进行回滚。而XA则是每个事务执行完成后会阻塞,等待全局事务执行完成再提交。