两阶段提交协议(2PC)、三阶提交协议(3PC)
2PC
二阶段提交协议是将事务的提交过程拆分为两个阶段来执行,分别为提交事务请求,执行事务请求
-
提交事务请求
协调者发送执行事务的请求给参与者,参与者执行事务,成功则返回YES,否则返回NO,并在本地记录Undo和Redo的信息
-
执行事务提交
如果协调者收到了参与者的失败消息或者超时,直接给每个参与者发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据协调者的指令执行提交或者回滚操作,释放所有事务处理过程中使用的锁资源
二阶段提交协议原理比价简单,实现方便,但是不幸的事,二阶段提交还是有几个缺点的:
1.同步阻塞:一旦参与者在等待其他参与者响应的过程中,它将无法再执行其他任何操作
2.单点问题:一旦协调者故障了,参与者将得不到任何请求,一直处于锁定事务资源状态,无法继续完成事务
3.数据不一致:在事务提交阶段,出现局部网络异常,导致部分协调者未接收到commit请求,就会造成已经接收到commit请求的参与者与未接到commit请求的参与者数据不一致
4.容错机制太过保守:任何一个节点的失败都会导致整个事务的失败
3PC
三阶段提交协议是2PC的改进版本,将2PC的提交事务阶段一分为二,这样就变成了三阶段:CanCommit,PreCommit,DoCommit三个阶段。
- CanCommit阶段
1.事务询问 协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应。
2.响应反馈 参与者接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则反馈No - PreCommit阶段
协调者根据参与者的反应情况来决定是否可以进行事务的PreCommit操作。1.发送预提交请求 协调者向参与者发送PreCommit请求,并进入Prepared阶段。
2.事务预提交 参与者接收到PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。
3.响应反馈 如果参与者成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令:提交(Commit)或中止(abort)。
假如有任何一个参与者向协调者发送了No响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。
- doCommit阶段
该阶段进行真正的事务提交。1.发送提交请求 协调接收到参与者发送的ACK响应,那么他将从预提交状态进入到提交状态。并向所有参与者发送doCommit请求。
2.事务提交 参与者接收到doCommit请求之后,执行正式的事务提交。并在完成事务提交之后释放所有事务资源。
3.响应反馈 事务提交完之后,向协调者发送Ack响应。
4.完成事务 协调者接收到所有参与者的ack响应之后,完成事务。
协调者没有接收到参与者发送的ACK响应,也可能是响应超时,那么就会执行中断事务。利用参与者二阶段记录的undo信息来执行事务回滚,并向协调者发送ACK消息,协调者收到ACK消息后执行事务中断
NOTE:
在doCommit阶段,如果参与者没有及时收到协调者的反馈(doCommit或abort),参与者都会进行事务的提交。因为一旦进入到doCommit阶段时,参与者有理由相信大家同意执行事务(所有协调者在canCommit反馈为YES,才会进入到preCommit阶段)
相对于2PC,3PC降低了参与者的阻塞范围,并且能在出现单点故障后继续保证事务的提交(见以上NOTE),但同样会导致数据一致性的问题,因为由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。
通过以上分析发现,2PC和3PC都无法彻底解决分布式的一致性问题,接下来会分析最为行之有效的Paxos算法
网友评论