理解:事务两阶段提交和三阶段提交(2PC、3PC)

目录

两阶段提交(2PC)

准备阶段:

提交阶段:

2PC存在的问题:

三阶段提交(3PC)

CanCommit:

PreCommit(如果CanCommit阶段中所有参与者都返回“Yes”)

DoCommit

3PC存在的问题:

3PC在2PC上的改动点:


两阶段提交(2PC)

图片来源:https://medium.com/@balrajasubbiah/consensus-two-phase-and-three-phase-commits-4e35c1a435ac

 

准备阶段:

1.协调者:向所有参与者发出“Request-to-Prepare”,进入提交阶段。

2.参与者:收到协调者的“Request-to-Prepare”,执行事务操作。

(1)事务执行成功,并写入Undo log和Redo log,返回“Prepared”。

(2)事务执行失败,返回“abort”。

 

提交阶段:

1.协调者:有超时机制
(1)如果所有参与者应答“Prepared”,协调者向所有参与者发出“Commit”。等待所有参与者返回“Done”,结束事务。

(2)如果存在参与者应答“Abort”,协调者向所有参与者发出“Rollback”。等待所有参与者返回“Done”,结束事务。

(3)如果到达协调者的超时时间,仍未收到所有参与者的应答,则向参与者发出“Rollback”。

2.参与者:

(1)收到“Commit”,完成操作,并释放在整个事务期间内占用的资源和锁,返回“Done”。

(2)收到“Rollback”,参与者利用之前写入的Undo信息执行回滚,并释放在整个事务期间内占用的资源,返回“Done”。

 

2PC存在的问题:

1.参与者无超时机制:一旦参与者故障,可能导致事务资源一直被锁定(同步阻塞);协调者故障,导致所有参与者一直锁定事务资源(单点故障)。

2.数据不一致:在提交阶段,部分参与者收到commit并执行commit,部分参与者因为网络等问题没收到消息导致无法执行事务提交。

3.无法解决:在提交阶段,协调者在发出第一个commit后宕机,唯一收到此commit消息的参与者也宕机。协调者重新选举出来后也不知道事务应该提交还是不提交。

 

三阶段提交(3PC)

图片来源:https://en.wikipedia.org/wiki/Three-phase_commit_protocol

 

状态扭转

图片来源:https://developer.jboss.org/wiki/Three-phaseCommitProtocol

 

CanCommit:

1.协调者:协调者向所有参与者询问“CanCommit”,协调者变更为waiting状态,等待参与者应答

(1)所有参与者返回“Yes”,协调者进入PreCommit阶段。

(2)有参与者返回“No”,协调者中断事务,并发送“abort”给所有参与者,变更为“aborted”状态。

(3)协调者等待超时,协调者中断事务,并发送“abort”给所有参与者,变更为“aborted”状态。

2.参与者:判断是否能提交事务

(1)能提交事务,返回“Yes”,变更为“waiting”状态。

(2)不能提交事务,返回“No”,变更为“abored”状态。

(3)接受到协调者的“abort”请求,变更为“aborted”状态。

 

PreCommit(如果CanCommit阶段中所有参与者都返回“Yes”)

1.协调者:发送“PrepareCommit”给所有参与者,协调者进入pre-commit状态,等待参与者应答。

(1)所有参与者都返回“ack”,进入DoCommit阶段。

(2)有参与者返回“abort”后,执行事务的中断,协调者向所有参与者发送“abort”,变更为“aborted”状态。

(3)协调者等待参与者应答的时候,协调者发生超时,协调者会中断事务,协调者向所有参与者发送“abort”,变更为“aborted”状态。

2.参与者:执行事务操作,并将undo和redo信息记录到事务日志中

(1)执行成功,返回“ack”,变更为“pre-commit”状态。

(2)执行失败,返回“abort”,变更为“aborted”状态。

(3)等待协调者的“PrepareCommit”超时,返回“abort”,变更为“aborted”状态。

(4)接收到协调者的“absort”请求,中断事务,变更为“aborted”状态。

 

DoCommit

1.协调者:如果所有参与者在PreCommit阶段都返回“ack”,则发送“commit”给所有参与者,协调者进入“commited”状态。

(1)协调者收到所有参与者的“ack”应答,事务结束。

(2)协调者等待参与者“ack”应答超时,协调者中断事务,发送“abort”给所有参与者,进入“aborted”状态。

2.协调者:如果有参与者返回“abort”,则发送“abort”给所有参与者,中断事务,协调者进入“aborted”状态。

3.参与者:根据协调者发出的命令进行操作

(1)参与者收到协调者的“commit”,执行事务提交,并释放所有的资源和锁,参与者进入“commited”状态。返回“ack”。

(2)参与者收到协调者的“abort”,根据undo日志进行回滚,并释放所有的资源和锁,参与者进入“aborted”状态,返回“ack”。

(3)参与者为“pre-commit”状态,没有收到协调者的“commit”或“abort”,会在等待超时后,提交事务(可能出现数据一致性的问题,例如参与者没有收到的消息是“abort”)。

 

3PC存在的问题:

1.数据不一致:在DoCommit阶段,如果因为网络问题,协调者发出的abort没有及时被参与者接收。这时候参与者最终执行了commit,就会引发数据不一致的问题。

2.需要更多的通讯次数,实现复杂

 

3PC在2PC上的改动点:

  • 在协调者和参与者中都引入超时机制(处理同步阻塞、单点故障问题)。
  • 将2PC的“准备阶段”切分成:CanCommit、DoCommit。在CanCommit阶段中尽早给出事务是否可以执行的判断,减少资源占用,提高吞吐量。
  • 在DoCommit阶段,即使协调者宕机,如果参与者不是abort和commited状态,就只能是pre-commit状态,最终也会提交事务。因为当该参与者是“pre-commit”状态时,意味着所有参与者都在CanCommit阶段中应答了,很大概率是可以成功执行事务的。因为在这3个阶段任意一个阶段中,如果任意一个参与者故障、超时、不能执行事务,协调者都会发送abort给所有参与者中断事务。

参考:

https://developer.jboss.org/wiki/Three-phaseCommitProtocol

https://en.wikipedia.org/wiki/Two-phase_commit_protocol

https://en.wikipedia.org/wiki/Three-phase_commit_protocol

http://www.hollischuang.com/archives/681

https://www.hollischuang.com/archives/1580

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章