分布式一致性协议:2PC与3PC

2022-09-03 09:15:14

前言

分布式系统进行架构设计的过程中,往往会在系统的可用性和数据一致性之间进行反复的权衡。

分布式系统中每个节点虽然能够明确知道自己在进行实物操作过程中的结果是成功或是失败,但却无法直接获取到其他节点的操作结果。

因此,当一个事物操作需要多个节点参与时,为了保持事物的ACID特性,就需要引入一个“协调者(Coordinate)”的角色来统一调度参与节点的执行逻辑,这些被调度的节点成为“参与者(Participant)”。协调者负责调度参与者的行为,并最终决定这些参与者是否把事物真正进行提交。

一、2PC(二阶提交)

2PC(Two-Phase Commit)即二阶提交,将事务分为两个阶段进行处理:提交事务请求、执行事务提交。

阶段一:提交事务请求

  1. 事务询问:协调者向所有参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的响应。
  2. 执行事务: 各参与者执行事务操作,并将Undo和Redo信息记入事务日志中。
  3. 参与者向协调者事务执行情况:如果参与者成功执行了事务,那么就反馈给协调者Yes响应,表示事务可以执行;如果参与者没有成功执行事务,那么就反馈给协调者No响应,表示事务不可以执行。

此阶段是各参与者投票是否继续执行下一步事务提交操作,因为此阶段也被称为“投票阶段”

阶段二:执行事务提交

阶段二会根据阶段一的反馈情况(投票情况)如果全部为Yes情况执行事务提交,如果反馈存在No或是等待响应超时执行事务中断

执行事务提交

  1. 发送提交请求: 协调者向所有参与者发送Commit请求。
  2. 事务提交:参与者接收到Commit请求后,会正式执行事务提交操作,并在完成提交之后释放在整个事务执行期占有的事物资源
  3. 反馈事务提交结果:参与者在完成事物提交之后,向协调者发送Ack消息。
  4. 完成事物:协调者接收到所有参与者反馈的Ack消息后,完成事物。

执行事务中断

  1. 发送回滚请求:协调者向所有参与者发送Rollback请求。
  2. 事物回滚:参与者收到Rollback请求后,会利用在阶段一种记录的Undo消息来执行事务回滚操心,并在完成回滚操作之后释放在整个事务执行期间占用的资源
  3. 反馈事务回滚结果:参与者在完成事物回滚之后,向协调者发送Ack消息。
  4. 事物中断:协调者接收到所有参与者反馈的Ack消息后,完成事物中断。

优缺点

优点:原理简单、实现方便。
缺点:同步阻塞、单点问题、脑裂、太过保守。

同步阻塞

二阶提交过程中,所有参与者在执行事务之后,需要等待到事务提交或是事务中断,之后餐能释放资源,而在这个等待的过程中将无法进行任何操作(处于阻塞状态)。

单点问题

协调者只有一个,一旦协调者出现问题,那么整个流程将无法运转。如果协调者在第二阶段开始出现问题,那么参与者将会一直处于锁定事务资源状态中,而无法继续完成事物操作。

因为只有协调者能够向参与者发起事物中断或是事务提交操作。

数据不一致

在阶段二,当协调者向所有参与者发送Commit请求之后,发生局部网络异常或者是协调者尚未发送完Commit请求之间自身发生崩溃,导致最终只有部分参与者收到Commit请求。收到请求的参与者会进行事物提交,而未收到的则在等待事物执行,导致整个分布式系统出现数据不一致,且部分节点事物阻塞。

太过保守

如果协调者在第一阶段过程中,参与者出现故障而导致协调者始终无法接受到参与者反馈信息,这是协调者只能依靠其自身的超时机制来判断是否需要中断事务。

二阶提交协议没有设计完善的容错机制,任意一个节点的失败都会导致整个事务的失败。

二、3PC(三阶提交)

3PC(Three-Phase Commit)三阶提交。是2PC的演化版本,将二阶提交中“提交事务请求”过程一分为二,形成由CanCommit、PreCommit和do Commit三个阶段组成事务处理协议。

阶段一:CanCommit(是否可执行事务提交操作)

  1. 事务询问:协调者向所有参与者发送一个包含事务内容的canCommit请求,询问是否可以执行事务提交操作,并开始等待各参与者的响应。
  2. 各参与者向协调者反馈事务询问的响应:参与者在接收到协调者发送的canCommit请求后,如果其自身认为可以执行事务,则会反馈Yes响应,并进入预备状态,否则反馈No响应。

阶段二:PreCommit(预提交事务)

根据阶段一的反馈情况:如果全部反馈为Yes则执行事务预提交,如果反馈中存在No响应或是等待超时之后则执行事务中断

事务预提交

  1. 发送预提交请求:协调者向所有参与者发送preCommit的请求,并进入Prepared阶段。
  2. 事务预提交:参与者接收到preCommit请求后,会执行事务操作,并将Undo和Redo信息记录到事务日志中。
  3. 参与者向协调者反馈事务执行响应:如果参与者成功执行了事务操作,那么就反馈给协调者Ack响应,同时等待最终命令:提交(commit)或是中止(abort)。否则反馈No响应。

事务中断

  1. 发送中断请求:协调者向所有参与者发送abort请求。
  2. 事务中断:无论是收到来之协调者的abort请求,或者是在等待协调者请求过程中出现超时,参与者都会中断事务。

阶段三:doCommit(执行提交事务)

协调者如果接受到所有参与者的Ack响应,则执行事务提交。如果任意一个参与者反馈了No响应,或者在等待超时之后,协调者尚未接收到参与者反馈响应,则执行事务中断

事务提交

  1. 发送事务提交请求:像所有参与者发送doCommit请求。
  2. 事务提交:参与者接收到doCommit请求后,会正式执行事务提交操作,并在完成提交之后释放在整个事务执行期占有的事物资源。
  3. 反馈事务提交结果:参与者在完成事物提交之后,向协调者发送Ack消息。
  4. 完成事物:协调者接收到所有参与者的反馈Ack消息后,完成事物。

事物中断

  1. 发送中断请求:协调者向所有参与者发送abort请求。
  2. 事物回滚:参与这个接收到abort请求后,会利用在阶段二中记录的Undo信息来执行事务回滚,并在完成事物回滚释放事务占用的资源。
  3. 反馈事务回滚结果:参与者在完成事物回滚之后,向反馈者发送Ack消息。
  4. 事物中断:协调者接收到所有参与者反馈的Ack消息后,中断事务。

注意点

进入阶段三,可以会出现以下两种情况:

  1. 协调者出现问题
  2. 协调者和参与者之间网络出现问题。

无论出现哪种情况,最终都会导致参与者无法及时接收来之协调者的doCommit或是abort请求,针对这种异常,参与者在等待超时之后,继续执行事务提交。

优缺点

优点:相对二阶提交协议,降低了参与者的阻塞范围,并且能在出现单点故障后继续达成一致。
缺点:在参与者接收到preCommit消息后,如果出现网络分区,此时协调者所在节点和参与者无法进行正常通信,在这种情况下,该参与者依然会进行事物的提交,导致数据不一致。

  • 作者:swg321321
  • 原文链接:https://blog.csdn.net/swg321321/article/details/125815450
    更新时间:2022-09-03 09:15:14