《从Paxos到ZooKeeper》一致性协议(一)
(一)2PC协议
即二阶段提交,目前绝大部分关系型数据库都是采用二阶段提交协议来完成分布式事务处理,保证分布式系统数据的一致性。
阶段一: 提交事务请求
- 事务询问:协调者向所有参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待个参与者的响应。
- 执行事务:各参与者节点执行事务操作,并将Undo和Redo信息计入事务日志中。
- 参与者向协调者反馈事务询问响应,如果成功,反馈YES,失败反馈NO。
阶段二: 执行事务提交
1.如果协调者获得的反馈都是YES,向参与者发出Commit请求,参与者接收到Commit请求后,会正式执行事务提交操作,并在完成提交之后释放在整个事务执行期间占用的事务资源。参与者在事务提交之后 向协调者发送Ack消息,协调者接收到所有参与者反馈的Ack消息后,完成事务。
2.如果任何一个参与者向协调者反馈了No响应,或者在等待超时之后,协调者尚无法接收到所有参与者的反馈相应,那么就会中断事务。参与者接收到Rollback请求后,会利用其在阶段一记录的Undo信息来执行事务回滚操作,并在完成回滚之后释放在整个事务执行期间占用的资源。反馈事务回滚结果,参与者完成事务回滚后,向协调者发送Ack消息。协调者接收到所有参与者反馈的Ack消息后,完成事务中断。
优缺点:
简单易懂,但是有同步阻塞(需要等其他节点的反馈)、可能数据不一致(Commit命令因网络问题丢失等),单点故障(严重依赖于协调者)。
(二)3PC协议
3PC协议将2PC的拆分为三个阶段,由CanCommit,PreCommit和doCommit三个阶段组成。
阶段一:CanCommit
1.事务询问,协调者向参与者发送一个canCommit,询问是否可以执行事务提交操作,并开始等待参与者响应。
2.各参与者向协调者反馈事务询问的响应,可以响应Yes,不可以反馈No响应。
阶段二:PreCommit
1.如果参与者反馈的都是YES,协调者向参与者发出PreCommit请求,参与者接收到preCommit请求后,会执行事务操作,并将Undo和Redo信息记录到事务日志中。参与者成功执行了事务操作,那么就会反馈给协调者Ack,同时等待最终的指令(doCommit或abort)。
2.如果任一参与者反馈了No响应,协调者会向参与者发送中断(abort)请求
阶段三:doCommit
1.如果参与者都反馈了Ack,那么协调者发送doCommit请求,参与者接收到doCommit请求后,会正式执行事务提交操作,并在完成提交后释放整个事务执行期间占用的资源,完成事务提交后,向协调者发送Ack消息,协调者收到所有参与者Ack消息后,完成事务。
2.收到任一No,协调者会发送abort命令,参与者根据Undo日志回滚。
阶段三种,如果参与者无法及时接收到来自协调者的doCommit或abort请求,针对这样的异常情况,参与者都会等待超时之后,继续进行事务提交。
优缺点
降低了阻塞范围(在二阶段提交中,参与者都阻塞在等待其他参与者的响应中,而在三阶段中,参与者在阻塞超时之后会直接提交,另外一个,由于有CanCommit的阶段,所以一旦有个参与者无法commit,其他参与者也不会进入阻塞)
单点故障也能继续提交
缺点:参与者如果接收到preCommit后,出现了网络分区,此时协调者所在节点和参与者无法进行正常的网络通信,在这种情况下,参与者依然会进行事务提交,容易造成数据不一致。