本文主要内容:
2pc 3pc
zookeeper 能做什么?
2PC 和 3PC
在分布式系统中,每一个机器节点虽然都能够明确的知道自己在进行事务操作过程中的结果是成功或失败,但却无法直接获取到其他分布式结点的操作结果。因此,当一个事务操作需要跨越多个分布式节点的时候,为了保持事务处理的 ACID 特性,就需要引入一个称为 “协调者 (Coordinator)” 的组件来统一调度所有分布式节点的执行逻辑,这些被调度的分布式节点则被称为 “参与者(Participant)”。协调者负责调度参与者的行为,并最终决定这些参与者是否要把事务真正进行提交。基于这个思想,衍生出了二阶段提交(2pc)和三阶段提交(3pc)两种协议。
2PC
第一阶段:提交事务请求
1.事务询问
协调者节点向所有参与者节点询问是否可以执行提交操作 (vote),并开始等待各参与者节点的响应。
2.执行事务
参与者节点执行询问发起为止的所有事务操作,并将 Undo 信息和 Redo 信息写入日志。(注意:若成功这里其实每个参与者已经执行了事务操作)
3.各参与者向协调者反馈事务询问的响应。
如果参与者节点的事务操作实际执行成功,则它返回一个”同意”消息;如果参与者节点的事务操作实际执行失败,则它返回一个”中止”消息。
第二阶段:执行事务提交
当协调者节点从所有参与者节点获得的相应消息都为”同意”时:
1.发送提交请求
协调者节点向所有参与者节点发出”正式提交 (commit) 的请求。
2.事务提交
参与者节点正式完成操作,并释放在整个事务期间内占用的资源。
3.反馈事务提交结果
参与者节点向协调者节点发送”完成”消息。
4.完成事务
协调者节点受到所有参与者节点反馈的”完成”消息后,完成事务。
中断事务
如果任一参与者节点在第一阶段返回的响应消息为”中止”,或者 协调者节点在第一阶段的询问超时之前无法获取所有参与者节点的响应消息时:
1.发送回滚请求
协调者节点向所有参与者节点发出”回滚操作 (rollback) 的请求。
2.事务回滚
参与者节点利用之前写入的 Undo 信息执行回滚,并释放在整个事务期间内占用的资源。
3.反馈事务回滚结果
参与者节点向协调者节点发送”回滚完成”消息。
4.中断事务
协调者节点受到所有参与者节点反馈的”回滚完成”消息后,取消事务。
2PC 的优缺点
优点:2PC 的优点是很显然的,原理简单,实现方便。目前,绝大多数关系型数据库都是采用两阶段提交协议来完成分布式事务处理的。(也就是上边的 2pc 过程应用于关系型数据库的分布式事务)
缺点:2PC 的缺点也很致命:同步阻塞,单点问题,数据不一致,太过保守
1、同步阻塞问题。执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态,各个参与者在等待协调者发出提交或中断请求时,会一直阻塞,而协调者的发出时间要依赖于所有参与者的响应时间,如果协调者宕机了(单点),那么他就一直阻塞在这,而且无法达成一致(3PC 引入了超时提交解决)。
2、单点故障。由于协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去。尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题)
3、数据不一致。出现分区,或者网络故障。在二阶段提交的阶段二中,当协调者向参与者发送 commit 请求之后,发生了局部网络异常或者在发送 commit 请求过程中协调者发生了故障,这回导致只有一部分参与者接受到了 commit 请求。而在这部分参与者接到 commit 请求之后就会执行 commit 操作。但是其他部分未接到 commit 请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据部一致性的现象。
4、太过保守:2pc 没有设计相应的容错机制,当任意一个参与者节点宕机,那么协调者超时没收到响应,就会导致整个事务回滚失败。
3PC
3PC,即三阶段提交,是 2 阶段提交的改进版,其将二阶段提交协议的“准备阶段”一份为二,形成了 cancommit,precommit,do commit 三个阶段。
CanCommit阶段
3PC 的 CanCommit 阶段其实和 2PC 的准备阶段很像。协调者向参与者发送 commit 请求,参与者如果可以提交就返回Yes响应,否则返回No响应。
1.事务询问
协调者向参与者发送 CanCommit 请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应。
2.响应反馈
参与者接到 CanCommit 请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回 Yes 响应,并进入预备状态。否则反馈 No
PreCommit阶段
协调者根据参与者的反应情况来决定是否可以记性事务的 PreCommit 操作。根据响应情况,有以下两种可能。
假如协调者从所有的参与者获得的反馈都是 Yes 响应,那么就会执行事务的预执行。
1.发送预提交请求
协调者向参与者发送 PreCommit 请求,并进入 Prepared 阶段。
2.事务预提交
参与者接收到 PreCommit 请求后,会执行事务操作,并将 undo 和 redo 信息记录到事务日志中。
3.响应反馈
如果参与者成功的执行了事务操作,则返回 ACK 响应,同时开始等待最终指令。
假如有任何一个参与者向协调者发送了 No 响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。
1.发送中断请求
协调者向所有参与者发送 abort 请求。
2.中断事务
参与者收到来自协调者的abort 请求之后(或超时之后,仍未收到协调者的请求),执行事务的中断。
doCommit阶段
执行提交
1.发送提交请求
协调接收到参与者发送的 ACK 响应,那么他将从预提交状态进入到提交状态。并向所有参与者发送 doCommit 请求。
2.事务提交
参与者接收到 doCommit 请求之后,执行正式的事务提交。并在完成事务提交之后释放所有事务资源。
3.响应反馈
事务提交完之后,向协调者发送 ack 响应。
4.完成事务
协调者接收到所有参与者的 ack 响应之后,完成事务。
中断事务
协调者没有接收到参与者发送的 ack 响应(可能是接受者发送的不是 ack 响应,也可能响应超时),那么就会执行中断事务。
1.发送中断请求
协调者向所有参与者发送 abort 请求
2.事务回滚
参与者接收到 abort 请求之后,利用其在阶段二记录的 undo 信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。
3.反馈结果
参与者完成事务回滚之后,向协调者发送 ack 消息
4.中断事务
协调者接收到参与者反馈的 ack 消息之后,执行事务的中断。
优缺点
三阶段提交协议的优点:相较于二阶段提交协议,三阶段提交协议最大的优点就是降低了参与者的阻塞范围,并且能够在出现单点故障后继续达成一致。
三阶段提交协议的缺点:三阶段提交协议在去除阻塞的同时也引入了新的问题,那就是在参与者接收到 perCommit 消息后,如果网络出现分区,此时协调者所在的节点和参与者无法进行正常的网络通信,在这种情况下,该参与者依然会进行事务的提交,这必然出现数据的不一致性。
zookeeper 能做什么?
-数据发布订阅
-负载均衡
-命名服务
-Master 选举
-集群管理
-配置管理
-分布式队列
-分布式锁