【Java高级工程师蜕变之路】055 分布式一致性协议之三阶段提交协议(3PC)
三阶段提交协议(3PC)
三阶段提交协议出现的背景:一致性协议中设计出了二阶段提交协议,但是2PC设计存在缺陷,于是有了三阶段提交协议。
三阶段提交协议
3PC,全称为“Three phase commit”,是2PC的改进版,将2PC的“事务提交过程”一分为二,并形成了canCommit、preCommit和doCommit三个阶段组成的事务处理协议。
三阶段提交升级点(基于二阶段):
-
三阶段提交协议引入了超时机制
-
在第一阶段和第二阶段中,引入了一个准备阶段。保证最后提交之前,各个节点之间数据一致性。
简单地说:除了引入超时机制外,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)协调者和参与者之间的网络故障
-
如果出现了任何一种情况,都可能出现参与者无法收到doCommit请求或者abort请求,参与者都会在等待超时之后进行事务提交。
3PC和2PC对比
对于协调者和参与者都设置了超时协议(在2PC中,只有协调者有超时机制,如果在一定时间内没有收到参与者的消息默认失败)。主要避免了参与者长时间无法与协调者节点通讯的情况下(或者协调者挂掉),无法释放资源的问题。因为参与者自身有超时机制,会在超时后,自动进行本地commit而释放资源。这种机制从侧面降低了整个事务的阻塞时间和范围。
通过canCommit、preCommit、doCommit三个阶段设计,相对于2PC而言,多设置了一个缓冲阶段,保证了最后提交阶段之前各个参与节点的状态一致。
preCommit是一个缓冲,保证了最后提交节点之前,各个节点的状态是一致的。
3PC没有完全解决数据一致性的问题。