分布式提交(2PC 和 3PC)

it2025-12-10  4

目的:保证多个参与者之间原子性

1、2PC

第一阶段(准备阶段):协调者节点向所有参与者节点询问是否可以执行提交操作(vote),并开始等待各参与者节点的响应。参与者节点执行所有事务操作,并将Undo信息和Redo信息写入日志(注意:若成功,这里每个参与者已经执行了事务操作)。各参与者节点响应协调者节点发起的询问。如果参与者节点的事务操作实际执行成功,则它返回一个”同意“消息;如果参与者节点的事务操作实际执行失败,则它返回一个”中止“消息。

第二阶段(提交阶段):如果协调者收到了参与者的失败消息或者超时。则直接给每个参与者发送回滚(rollback)消息;否者,发送提交(commit)消息;参与者根据协调者的指令执行提交或回滚操作,释放所有事务处理过程中使用的锁资源(注意:必须在最后阶段释放资源)。

当协调者节点从所有参与者节点处获得的相应消息都为同意时:

  协调者节点向所有参与者节点发出”正式提交(commit)“的请求。

  参与者节点正式完成操作,并释放在整个事务期间内占用的的资源。

  参与者节点向协调者节点发送”完成“消息。

如果任一参与者节点在第一阶段返回的响应消息为”中止“,或者协调者节点在第一阶段的询问在超时之前无法获取所有参与者节点的响应消息时:

  协调者节点向所有参与者节点发出”回滚操作(rollback)“的请求。

  参与者节点利用之前写入的Undo信息执行回滚,并释放在整个事务期间占用的资源。

  参与者节点向协调者节点发送”回滚完成“消息

  协调者节点收到所有参与者节点反馈的”回滚完成“消息后,取消事务。

  协调者节点收到所有参与者节点反馈的”完成“消息后,完成事务。

不管最后怎样,第二阶段都会结束当前事务

 

二阶段缺点:

  同步阻塞问题。在执行过程中,所有参与节点都是事务阻塞型的。

  单点故障。由于协调者的重要性,一旦协调者发生故障,参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者都还处于锁定事务资源的状态,而无法继续完成事务操作。

  数据不一致。在阶段二中,当协调者向参与者发送commit请求后,发生了局部网络异常,或者在发送commit请求过程中协调者发生了故障,这会导致只有一部分参与者接收到了commit请求。而在这部分参与者接收到commit请求之后就会执行commit操作,但时其他部分未接收到commit请求的机器则无法执行事务提交操作。于是整个分布式系统便出现了数据不一致的现象。

  两阶段无法解决的问题:协调者再发出commit消息之后宕机,而唯一接收到这条消息的参与者也同时宕机了,那么即使协调者通过选举协议产生了新的协调者。这条事务的状态也是不确定的。没人知道事务是否已经被提交。

为了解决以上问题,提出三阶段

 

2、3PC

三阶段与二阶段相比:

  1)引入超时机制,同时在协调者和参与者中都引入超时机制。

  2)在第一阶段和第二阶段中插入一个准备阶段,保证在最后提交阶段之前各参与节点的状态是一致的。

CanCommit阶段:协调者向参与者发送commit请求,参与者如果可以提交就返回yes响应,否则返回no响应。

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

  响应反馈:参与者接收到CanCommit请求之后,在正常情况下,如果其自身认为可以顺利执行事务(并未执行),则返回yes响应,进入预备状态,否则返回no响应。

 

PreCommit阶段

假如协调者从所有参与者处获得的反馈都是yes响应,那么就会执行事务的预执行。

  发送预提交请求:协调者向参与者发送PreCommit请求,并进入Prepared阶段。

  事务预提交:参与者接收到PreCommit请求后,会执行事务操作,并将Undo和Redo信息记录到事务日志中。

  响应反馈:如果参与者成功地执行了事务操作,则返回ACK响应,同时开始等待最终指令。假如任何一个参与者向协调者发送了no响应,或者等待超时之后,协调者都没有接收到参与者的响应,那么就执行事务的中断操作。

  发送中断请求:协调者向所有参与者发送abort请求。

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

 

DoCommit阶段:进行事务的提交

  执行提交

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

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

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

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

中断事务:协调者没有接收到参与发送的ACK响应,那么就会执行中断事务操作。

    发送中断请求:协调向所有参与者发送abort请求。

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

    反馈结果:参与者完成事务回滚之后,向协调者发送ACK消息。

    中断事务:协调者接收到参与者反馈的ACK消息之后,执行事务的中断操作。

最新回复(0)