This commit is contained in:
by931
2022-09-06 22:30:37 +08:00
parent 66970f3e38
commit 3d6528675a
796 changed files with 3382 additions and 3382 deletions

View File

@@ -198,7 +198,7 @@ function hide_canvas() {
<p>ZooKeeper 最核心的作用就是保证分布式系统的数据一致性,而无论是处理来自客户端的会话请求时,还是集群 Leader 节点发生重新选举时都会产生数据不一致的情况。为了解决这个问题ZooKeeper 采用了 ZAB 协议算法。</p>
<p><strong>ZAB 协议算法</strong>Zookeeper Atomic Broadcast Zookeeper 原子广播协议)是 ZooKeeper 专门设计用来解决集群最终一致性问题的算法,它的两个核心功能点是<strong>崩溃恢复</strong><strong>原子广播协议</strong></p>
<p>在整个 ZAB 协议的底层实现中ZooKeeper 集群主要采用<strong>主从模式</strong>的系统架构方式来保证 ZooKeeper 集群系统的一致性。整个实现过程如下图所示,当接收到来自客户端的事务性会话请求后,系统集群采用主服务器来处理该条会话请求,经过主服务器处理的结果会通过网络发送给集群中其他从节点服务器进行数据同步操作。</p>
<p><img src="assets/Ciqc1F8zqzWAY5J1AAAlia-QXZo498.png" alt="Drawing 0.png" /></p>
<p><img src="assets/Ciqc1F8zqzWAY5J1AAAlia-QXZo498.png" alt="png" /></p>
<p>以 ZooKeeper 集群为例,这个操作过程可以概括为:当 ZooKeeper 集群接收到来自客户端的事务性的会话请求后,集群中的其他 Follow 角色服务器会将该请求转发给 Leader 角色服务器进行处理。当 Leader 节点服务器在处理完该条会话请求后,会将结果通过操作日志的方式同步给集群中的 Follow 角色服务器。然后 Follow 角色服务器根据接收到的操作日志,在本地执行相关的数据处理操作,最终完成整个 ZooKeeper 集群对客户端会话的处理工作。</p>
<h4>崩溃恢复</h4>
<p>在介绍完 ZAB 协议在架构层面的实现逻辑后,我们不难看出整个 ZooKeeper 集群处理客户端会话的核心点<strong>在一台 Leader 服务器上</strong>。所有的业务处理和数据同步操作都要靠 Leader 服务器完成。结合我们在“ 28 | 彻底掌握二阶段提交/三阶段提交算法原理” 中学习到的二阶段提交知识,会发现就目前介绍的 ZooKeeper 架构方式而言,<strong>极易产生单点问题</strong>,即当集群中的 Leader 发生故障的时候,整个集群就会因为缺少 Leader 服务器而无法处理来自客户端的事务性的会话请求。因此,为了解决这个问题。在 ZAB 协议中也设置了处理该问题的崩溃恢复机制。</p>
@@ -206,7 +206,7 @@ function hide_canvas() {
<p><strong>投票过程如下</strong>:当崩溃恢复机制开始的时候,整个 ZooKeeper 集群的每台 Follow 服务器会发起投票,并同步给集群中的其他 Follow 服务器。在接收到来自集群中的其他 Follow 服务器的投票信息后,集群中的每个 Follow 服务器都会与自身的投票信息进行对比,如果判断新的投票信息更合适,则采用新的投票信息作为自己的投票信息。在集群中的投票信息还没有达到超过半数原则的情况下,再进行新一轮的投票,最终当整个 ZooKeeper 集群中的 Follow 服务器超过半数投出的结果相同的时候,就会产生新的 Leader 服务器。</p>
<h4>选票结构</h4>
<p>介绍完整个选举 Leader 节点的过程后,我们来看一下整个投票阶段中的投票信息具有怎样的结构。以 Fast Leader Election 选举的实现方式来讲,如下图所示,一个选票的整体结果可以分为一下六个部分:</p>
<p><img src="assets/CgqCHl8zq1SABNDvAAB3WcgZ-2s055.png" alt="Drawing 1.png" /></p>
<p><img src="assets/CgqCHl8zq1SABNDvAAB3WcgZ-2s055.png" alt="png" /></p>
<ul>
<li><strong>logicClock</strong>用来记录服务器的投票轮次。logicClock 会从 1 开始计数每当该台服务经过一轮投票后logicClock 的数值就会加 1 。</li>
<li><strong>state</strong>:用来标记当前服务器的状态。在 ZooKeeper 集群中一台服务器具有 LOOKING、FOLLOWING、LEADERING、OBSERVING 这四种状态。</li>
@@ -218,12 +218,12 @@ function hide_canvas() {
<p>当 ZooKeeper 集群需要重新选举出新的 Leader 服务器的时候,就会根据上面介绍的投票信息内容进行对比,以找出最适合的服务器。</p>
<h4>选票筛选</h4>
<p>接下来我们再来看一下,当一台 Follow 服务器接收到网络中的其他 Follow 服务器的投票信息后是如何进行对比来更新自己的投票信息的。Follow 服务器进行选票对比的过程,如下图所示。</p>
<p><img src="assets/Ciqc1F8zq2CAABxRAACKTM36L6o309.png" alt="2.png" /></p>
<p><img src="assets/Ciqc1F8zq2CAABxRAACKTM36L6o309.png" alt="png" /></p>
<p>首先,会对比 logicClock 服务器的投票轮次,当 logicClock 相同时,表明两张选票处于相同的投票阶段,并进入下一阶段,否则跳过。接下来再对比 vote_zxid 被选举的服务器 ID 信息,若接收到的外部投票信息中的 vote_zxid 字段较大,则将自己的票中的 vote_zxid 与 vote_myid 更新为收到的票中的 vote_zxid 与 vote_myid ,并广播出去。要是对比的结果相同,则继续对比 vote_myid 被选举服务器上所保存的最大事务 ID ,若外部投票的 vote_myid 比较大,则将自己的票中的 vote_myid 更新为收到的票中的 vote_myid 。 经过这些对比和替换后,最终该台 Follow 服务器会产生新的投票信息,并在下一轮的投票中发送到 ZooKeeper 集群中。</p>
<h4>消息广播</h4>
<p>在 Leader 节点服务器处理请求后需要通知集群中的其他角色服务器进行数据同步。ZooKeeper 集群采用消息广播的方式发送通知。</p>
<p>ZooKeeper 集群使用原子广播协议进行消息发送,该协议的底层实现过程与我们在“ 28 | 彻底掌握二阶段提交/三阶段提交算法原理” 的二阶段提交过程非常相似,如下图所示。</p>
<p><img src="assets/Ciqc1F8zq2qAXTCIAAB2wqjPhfI084.png" alt="Drawing 3.png" /></p>
<p><img src="assets/Ciqc1F8zq2qAXTCIAAB2wqjPhfI084.png" alt="png" /></p>
<p>当要在集群中的其他角色服务器进行数据同步的时候Leader 服务器将该操作过程封装成一个 Proposal 提交事务,并将其发送给集群中其他需要进行数据同步的服务器。当这些服务器接收到 Leader 服务器的数据同步事务后,会将该条事务能否在本地正常执行的结果反馈给 Leader 服务器Leader 服务器在接收到其他 Follow 服务器的反馈信息后进行统计,判断是否在集群中执行本次事务操作。</p>
<p>这里请大家注意 ,与我们“ 28 | 彻底掌握二阶段提交/三阶段提交算法原理” 中提到的二阶段提交过程不同(即需要集群中所有服务器都反馈可以执行事务操作后,主服务器再次发送 commit 提交请求执行数据变更) ZAB 协议算法省去了中断的逻辑,当 ZooKeeper 集群中有超过一般的 Follow 服务器能够正常执行事务操作后,整个 ZooKeeper 集群就可以提交 Proposal 事务了。</p>
<h3>总结</h3>