分布式系统原理( 二 )

2.2 三阶段提交协议:3PC2.2.1 概述三阶段提交(Three-phase commit),是为解决两阶段提交协议的缺点而设计的 。与两阶段提交不同的是,三阶段提交是“非阻塞”协议 。
三阶段提交在两阶段提交的第一阶段与第二阶段之间插入了一个准备阶段,使得原先在两阶段提交中,参与者在投票之后,由于协调者发生崩溃或错误,而导致参与者处于无法知晓是否提交或者中止的“不确定状态”所产生的可能相当长的延时的问题得以解决 。
2.2.2 三阶段提交过程

分布式系统原理

文章插图
 
image.png
询问阶段:CanCommit 协调者向参与者发送 Commit 请求,参与者如果可以提交就返回 Yes 响应,否则返回 No 响应 。
准备阶段:PreCommit 协调者根据参与者在询问阶段的响应判断是否执行事务还是终端事务: 如果所有参与者都返回 Yes,则执行事务 。如果参与者有一个或多个参与者返回 No 或者超时,则中断事务 。参与者执行完操作之后返回 ACK 响应,同时开始等待最终指令
提交阶段:DoCommit 协调者根据参与者在准备阶段的响应判断是否执行事务还是中断事务: 如果所有参与者都返回正确的 ACK 响应,则提交事务 。如果参与者有一个或多个参与者收到错误的 ACK 响应或者超时,则中断事务 。如果参与者无法及时接收到来自协调者的提交或者中断事务请求时,会在等待超时之后,会继续进行事务提交 。协调者收到所有参与者的 ACK 响应,完成事务 。
2.2.3 解决二阶段提交时的问题:三阶段提交解决了二阶段提交中存在的由于协调者和参与者同时挂掉可能导致的数据一致性问题和单点故障问题,并减少阻塞 。因为一旦参与者无法及时收到来自协调者的信息之后,他会默认执行提交事务(三阶段),而不会一直持有事务资源并处于阻塞状态(二阶段会) 。
2.2.4 三阶段提交的问题:在提交阶段如果发送的是中断事务请求,但是由于网络问题,导致部分参与者没有接到请求 。
那么参与者会在等待超时之后执行提交事务操作,这样这些由于网络问题导致提交事务的参与者的数据就与接受到中断事务请求的参与者存在数据不一致的问题 。
【分布式系统原理】所以无论是 2PC 还是 3PC 都不能保证分布式系统中的数据 100% 一致 。
2.3 ZAB——zookeeper 原子广播协议2.3.1 概述ZAB 协议全称是Zookeeper Atomic Broadcast,是为分布式协调服务 Zookeeper 专门设计的一种支持 崩溃恢复 和 原子广播 协议 。ZAB 协议满足CP,在选举过程中,是不能对外提供服务的 。
2.3.3 消息广播ZAB 协议的消息广播过程(即数据同步过程)使用的是一个原子广播协议,类似一个 二阶段提交过程 。对于客户端发送的写请求,全部由 Leader 接收,Leader 将请求封装成一个事务 Proposal,将其发送给所有 Follwer ,然后,根据所有 Follwer 的反馈,如果超过半数成功响应,则执行 commit 操作(先提交自己,再发送 commit 给所有 Follwer) 。
广播流程:
分布式系统原理

文章插图
 
image.png
  • 客户端发起一个写操作请求 。
  • Leader 服务器将客户端的请求转化为事务 Proposal 提案,同时为每个 Proposal 分配一个全局的ID,即zxid 。然后将需要广播的Proposal 依次放到队列中,并且根据 FIFO 策略进行消息发送 。
  • Follower 接收到 Proposal 后,会首先将其以事务日志的方式写入本地磁盘中,写入成功后向 Leader 反馈一个 Ack 响应消息 。
  • Leader 接收到超过半数以上 Follower 的 Ack 响应消息后,即认为消息发送成功,可以发送 commit 消息 。
  • Leader 向所有 Follower 广播 commit 消息,同时自身也会完成事务提交 。Follower 接收到 commit 消息后,会将上一条事务提交 。
注意: 1、 Leader 服务器与每一个 Follower 服务器之间都维护了一个单独的 FIFO 消息队列进行收发消息,使用队列消息可以做到异步解耦 。Leader 和 Follower 之间只需要往队列中发消息即可 2、Leader 在收到客户端请求之后,会将这个请求封装成一个事务,并给这个事务分配一个全局递增的唯一 ID,称为事务ID(ZXID),ZAB 协议需要保证事务的顺序,因此必须将每一个事务按照 ZXID 进行先后排序然后处理 3、可以认为这是一种简化版本的 2PC,2PC的单点问题(Leader崩溃)这里也会遇到,ZAB是通过崩溃恢复来解决的


推荐阅读