【Java高级工程师蜕变之路】055 分布式一致性协议之三阶段提交协议(3PC)

三阶段提交协议(3PC)

三阶段提交协议出现的背景:一致性协议中设计出了二阶段提交协议,但是2PC设计存在缺陷,于是有了三阶段提交协议。

三阶段提交协议

3PC,全称为“Three phase commit”,是2PC的改进版,将2PC的“事务提交过程”一分为二,并形成了canCommit、preCommit和doCommit三个阶段组成的事务处理协议。

image-20220320223801310

三阶段提交升级点(基于二阶段):

  • 三阶段提交协议引入了超时机制

  • 在第一阶段和第二阶段中,引入了一个准备阶段。保证最后提交之前,各个节点之间数据一致性。

    简单地说:除了引入超时机制外,3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有,CanCommit、

    preCommit、doCommit三个阶段。

三阶段详解

  • 第一阶段(canCommit)

    类似于2PC的准备阶段(preCommit)。

    协调者向参与者发送Commit请求,参与者如果可以提交就发生yes响应,否则返回No响应。

    • 事务询问

      协调者向参与者发送canCommit请求。询问是否可以进行事务提交操作,然后开始等待参与者的响应。

    • 响应反馈

      参与者接收到canCommit请求之后,正常情况下,如果自身可以执行事务,则返回Yes响应,并进入预备状态。否则反馈No

  • 第二阶段(preCommit)

    协调者根据参与者的反应情况,来决定是否可以执行事务的preCommit操作。根据响应情况,有以下两种可能:

    • Yes

      (1)发送预提交请求

      协调者向参与者发送preCommit请求,并进入prepared阶段。

      (2)事务预提交

      参与者接收到preCommit请求之后,会执行事务操作,并将undo信息和redo信息记录到事务日志中。

      (3)响应反馈

      如果参与者成功执行了事务操作,则返回ACK响应,并且开始等待最终指令。

    • No

      假设任何一个向协调者发送了No响应,或者等待超时之后,协调者都没有接收到参与者的响应,那么就执行事务的中断。

      (1)发送中断请求

      协调者向参与者发送abort请求

      (2)中断事务

      参与者收到来着协调者的abort请求之后(或者超时仍未收到协调者的请求),执行事务的中断

  • 第三阶段(doCommit)

    该阶段进行真正的事务提交,也可以分为执行事务和中断事务两种情况

    • 执行成功

      (1)发送提交请求

      协调者接收到参与者发送的ACK响应,那么它从预提交状态进入到提交状态。并向所有参与者发送doCommit请求。

      (2)事务提交

      参与者接收到doCommit请求之后,执行正式的事务提交。并在完成事务提交之后释放所有的事务资源。

      (3)响应反馈

      事务提交完之后,向协调者发送ACK响应。

      (4)完成事务

      协调者接收到所有参与者的ACK响应之后,完成事务。

    • 中断事务

      (1)发送中断请求

      协调者向所有参与者发送abort请求

      (2)事务回滚

      参与者接收到abort请求之后,利用在阶段二记录的undo信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。

      (3)反馈结果

      参与者完成事务回滚之后,想协调者发送ACK消息

      (4)中断事务

      协调者接收到所有参与者的ACk消息之后,进行事务的中断

      一旦进入阶段三,可能会有两种故障

      (1)协调者出现问题

      (2)协调者和参与者之间的网络故障

image-20220327152939588

如果出现了任何一种情况,都可能出现参与者无法收到doCommit请求或者abort请求,参与者都会在等待超时之后进行事务提交。

3PC和2PC对比

对于协调者和参与者都设置了超时协议(在2PC中,只有协调者有超时机制,如果在一定时间内没有收到参与者的消息默认失败)。主要避免了参与者长时间无法与协调者节点通讯的情况下(或者协调者挂掉),无法释放资源的问题。因为参与者自身有超时机制,会在超时后,自动进行本地commit而释放资源。这种机制从侧面降低了整个事务的阻塞时间和范围。

通过canCommit、preCommit、doCommit三个阶段设计,相对于2PC而言,多设置了一个缓冲阶段,保证了最后提交阶段之前各个参与节点的状态一致。

preCommit是一个缓冲,保证了最后提交节点之前,各个节点的状态是一致的。

3PC没有完全解决数据一致性的问题。

posted @ 2022-05-04 22:34  灯塔下的守望者  阅读(79)  评论(0编辑  收藏  举报