Three‐Phase Commit - tenji/ks GitHub Wiki

三阶段提交

三阶段提交(英语:Three-phase commit),也叫三阶段提交协议(英语:Three-phase commit protocol),是在电脑网络及数据库的范畴下,令一个分布式系统内的所有节点能够执行事务的提交的一种分布式算法。三阶段提交是为了解决两阶段提交协议的缺点而设计的。

一、基本算法

第一阶段(CanCommit 准备阶段)

该阶段协调者会去询问各个参与者是否能够正常执行事务,参与者根据自身情况回复一个预估值,相对于真正的执行事务,这个过程是轻量的,具体步骤如下:

  1. 协调者向各个参与者发送事务询问通知,询问是否可以执行事务操作,并等待回复;
  2. 各个参与者依据自身状况回复一个预估值,如果预估自己能够正常执行事务就返回确定信息,并进入预备状态,否则返回否定信息。

第二阶段(PreCommit 阶段)

成功

当所有的参与者都返回确定信息时:

  1. 协调者向所有的事务参与者发送事务执行通知;
  2. 参与者收到通知后执行事务但不提交;
  3. 参与者将事务执行情况返回给客户端。

失败

当一个或多个参与者返回否定信息或协调者等待超时时:

  1. 协调者向所有事务参与者发送 abort 通知;
  2. 参与者收到通知后中断事务。

第三阶段(DoCommit 阶段)

成功

当所有的参与者都能正常执行事务时:

  1. 协调者向所有参与者发送事务 commit 通知;
  2. 所有参与者在收到通知之后执行 commit 操作,并释放占有的资源;
  3. 参与者向协调者反馈事务提交结果。

失败

当一个或多个参与者执行事务失败或协调者等待超时时:

  1. 协调者向所有参与者发送事务 rollback 通知;
  2. 所有参与者在收到通知之后执行 rollback 操作,并释放占有的资源;
  3. 参与者向协调者反馈事务回滚结果。

进入 DoCommit 阶段后,无论协调者出现问题,或者协调者与参与者之间的网络出现问题,都会导致参与者无法接收到协调者发出的 DoCommit 请求或 abort 请求。此时,参与者都会在等待超时之后,继续执行事务提交。这其实基于概率来决定的,当进入第三阶段时,说明第一阶段收到所有参与者的 CanCommit 响应都是 Yes,意味着大家都同意修改了,并且第二阶段所有的参与者对协调者的 PreCommit 请求也都是同意的。所以,一句话概括就是,当进入第三阶段时,由于网络超时等原因,虽然参与者没有收到 commit 或者 abort 响应,但是他有理由相信:成功提交的几率很大。

基本流程图

基本流程图

二、状态转换

状态转换

三、2PC vs 3PC

2PC 和 3PC 是分布式事务中两种常见的协议,3PC 可以看作是 2PC 协议的改进版本,相比于 2PC 它有两点改进:

  1. 引入了超时机制,同时在协调者和参与者中都引入超时机制(2PC 只有协调者有超时机制);
  2. 3PC 相比于 2PC 增加了 CanCommit 阶段,保证了在最后提交阶段之前各参与节点的状态是一致的(但是同时也会提高系统复杂度以及带来更高的系统开销)。

也就是说,3PC 相比于 2PC,因为引入了超时机制,所以发生阻塞的几率变小了;同时 3PC 把之前 2PC 的准备阶段一分为二,变成了两步,这样就多了一个缓冲阶段,保证了在最后提交阶段之前各参与节点的状态是一致的。

四、数据一致性问题和解决方案

3PC 虽然可以减少同步阻塞问题和单点故障问题,但依然存在数据一致性问题(概率很小),而解决数据一致性问题的方案有很多,比如 Paxos 算法或柔性事物机制等。

∞、参考链接