本文内容为《从PAXOS到ZOOKEEPER分布式一致性原理与实践》一书学习笔记。本文主要概述第二章内容。
一致性协议和算法:解决分布式系统数据一致性问题。
分布式系统中,每个节点可以明确知道自己在进行事务操作中的结果是成功还是失败,但无法直接获取到其他分布式节点的操作结果。所以当事务操作需要跨越多个分布式节点时,为了保持事务处理的ACID特性,引入协调者这个概念。
协调者统一调度所有分布式节点的执行逻辑,这些被调度的分布式节点被称为参与者。协调者负责调度参与者的行为,并最终决定这些参与者是否要把事务真正进行提交。基于这个思想衍生出了2PC和3PC两种协议。
2PC(Two-Phase Commit):二阶段提交,一种一致性协议。保证分布式架构中的节点在进行事务处理过程中的原子性和一致性。
阶段一:提交事务请求(投票)。
- 协调者向所有参与者询问,是否可以执行事务提交。
- 参与者执行事务。
- 参与者向协调者反馈事务询问的响应。成功执行事务操作反馈Yes,否则为No。
阶段二:执行事务提交(确认投票是否通过)
如果所有参与者反馈都是Yes,执行事务提交
- 协调者向所有参与者发送提交请求。
- 参与者执行事务提交并释放事务执行期间占用的事务资源。
- 参与者完成事务提交后反馈ACK。
- 协调者收到所有参与者反馈的ACK后,完成事务提交。
如果有任何一个参与者反馈是No或者等待超时无法收到该参与者的反馈,执行事务中断
- 协调者向所有参与者发送回滚请求。
- 参与者执行事务回滚并释放事务执行期间占用的事务资源。
- 参与者完成事务回滚后反馈ACK。
- 协调者收到所有参与者反馈的ACK后,完成事务中断。
2PC核心是对每个事务都采用先尝试后提交的处理方式,所以可以看作是强一致性的算法。
2PC优点:原理简单,实现方便
2PC缺点:同步阻塞、单点故障、脑裂、太过保守。
同步阻塞:二阶段提交的执行过程中,所有参与该事务操作的逻辑都处于阻塞状态。各个参与者在等待其他参与者响应的过程中,无法进行其他操作。
单点问题:协调者若是在阶段二出现问题,其他参与者会一直处于锁定事务资源的状态,无法继续完成事务操作。
数据不一致(脑裂的后果):在阶段二执行事务提交的时候,协调者向所有参与者发送提交请求之后发生了局部网络异常或协调者在尚未发送完提交请求之前自身发生了崩溃,导致最终只有部分参与者收到了提交请求。这部分收到了提交请求的参与者会提交事务,没收到提交请求的参与者无法进行提交(书中这点讲解的太笼统,此处的参与者不一定无法提交,协调者可以重新选举;出现数据不一致有两个原因,一是协调者和收到通知的那部分参与者同时崩溃,二是脑裂;具体可以参考漫谈分布式系统(10) -- 初探分布式事务),整个分布式系统会出现数据不一致。
太过保守:任一节点的失败都会导致整个事务的失败。
3PC:与两阶段提交不同的是,三阶段提交有两个改动点。
1、引入超时机制。同时在协调者和参与者中都引入超时机制。2PC只有协调者有超时机制。
2、在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
将2PC的提交事务流程(投票)分成新阶段一(CanCommit)和新阶段二(PreCommit),原本的阶段二是现在的阶段三(do commit)。
阶段一(CanCommit):
- 协调者向参与者询问是否可以执行事务提交操作(canCommit请求)(尝试获取数据库锁,见链接 )
- 参与者如果认为自身可以顺利执行事务,反馈Yes,并进入预备状态。
阶段二(PreCommit):
根据参与者的反馈来决定:
如果所有参与者反馈都是Yes,执行事务预提交:
- 协调者向参与者发送预提交请求(PreCommit请求)
- 事务预提交。参与者执行事务操作
- 参与者向协调者反馈事务执行的响应
如果有任何一个参与者反馈是No或者等待超时无法收到该参与者的反馈,执行事务中断
- 协调者向参与者发送中断请求(abort)
- 参与者中断事务。(等待协调者请求过程中超时,参与者也会中断事务)
阶段三同2PC的阶段二,执行提交那么协调者发送doCommit请求,执行中断事务那么协调者发送abort请求。但有一点不同,协调者出现问题或者协调者和参与者之间的网络出现故障都会导致参与者无法及时接收到来自协调者的doCommit或是abort请求,此时参与者都会在等待超时后继续进行事务提交。
3PC优点:与2PC相比解决了单点故障问题,并减少了参与者阻塞范围。因为一旦参与者无法及时收到来自协调者的信息之后,它会默认执行commit。而不会一直持有事务资源,并处于阻塞状态。
3PC缺点:参与者收到preCommit消息后,如果出现网络分区,协调者和参与者不能正常通信,此时参与者依然会进行事务提交,导致数据不一致,引入了新的数据不一致的可能性。(由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。)
网友评论