蚂蚁面试官:Zookeeper 的选举流程是怎样的?我当场懵逼了。。。 た 入场券 2022-08-28 05:46 114阅读 0赞 栈长面试经常会遇到面试官问 Zookeeper 的选举原理,我心想,问这些有啥用吗?又不要我造火箭! 每次面试也只知道个大概,并没有深究具体的流程,所以在面试的时候总是不能打动面试官,总是特别吃亏,所以这篇就总结一下其中的要点,也希望能帮助大家搞定面试。 有一说一, Zookeeper 这些工作原理、选举流程,也许大多数人在工作中不会用到,但了解多一点也是自己的优势,避免求职面试被面试官打压工资。Zookeeper 也是现在后端主流的分布式协调框架,很多热门框架都有直接或者间接依赖它,比如:Dubbo、Elastic Job、Kafka 等,所以掌握 ZK 选举流程也是非常有必要的。 本文会以通俗易懂的方式进行, ZK 小白也能看懂。另外,我也将 Zookeeper 系列主流面试题和参考答案都整理好了,关注公众号Java技术栈回复关键字 "面试" 进行刷题。 ## 基本概念 ## 了解选举前你得了解一些 Zookeeper 的基本概念。 #### 集群机器 ID #### 集群机器 ID 是指 myid,它是每一个集群机器中的编号文件,代表 ZooKeeper 集群服务器的标识,手动生成,全局全一。 #### 事务 ID #### 事务 ID 是指 zxid,Zookeeper 会给每个更新请求分配一个事务 ID,它是一个 64 位的数字,由 Leader 统一进行分配,全局唯一,不断递增,在一个节点的状态信息中可以查看到最新的事务 ID 信息。 #### 集群服务器角色 #### Zookeeper 集群服务器有以下 3 种角色: 1、Leader(主) 2、Follower(从,参与投票) 3、Observer(观察者,不参与投票) #### 集群服务器状态 #### Zookeeper 集群服务器有以下 4 种状态: **1、LOOKING** 寻找 Leader 状态,当服务器处于该状态时,表示当前集群没有 Leader,因此会进入 Leader 选举状态。 **2、FOLLOWING** 跟随者状态,表示当前服务器角色是 Follower。 **3、LEADING** 领导者状态,表示当前服务器角色是 Leader。 **4、OBSERVING** 观察者状态,表示当前服务器角色是 Observer。 #### **选举方式** #### Zookeeper 提供了 3 种选举方式: * LeaderElection * AuthFastLeaderElection * **FastLeaderElection (最新默认)** #### 选举场景 #### Zookeeper 会在以下场景进行选举: 1、Zookeeper 集群启动初始化时进行选举 2、Zookeeper 集群 Leader 失联时重新选举 #### 选举前提条件 #### **1、Zookeeper 服务器处于 LOOKING 竞选状态** 此时说明 Zookeeper 服务器集群处于群龙无首状态,另外,观察者状态不能参与竞选投票。 **2、Zookeeper 集群规模至少要 3 台机器或以上** 集群规则为:2N + 1台,N > 0,即最少需要 3 台,因为 ZK 集群的机制是只要超过半数的节点正常,集群就能正常提供服务。只有在 ZK 节点挂得太多,只剩一半或不到一半节点能工作时,集群才会失效。 **如以下分析所示:** > 3 个节点的 Cluster 可以挂掉 1 个节点(Leader 可以得到 2 票 > 1.5) > > 2 个节点的 Cluster 就不能挂掉任何 1 个节点了(Leader 可以得到 1 票 <= 1) 所以你知道 ZK 集群为什么至少要 3 台了吧? **3、Zookeeper 集群要 2 台及以上机器可以互相通信** 只要达到 2 台服务器通信了才能进行选举,只有一台服务器启动时无法进行选举,因为服务器之间通信了才可以互相同步投票结果。 ## 选举流程 ## ### 1、集群初始选举 ### Zookeeper 在集群启动时会进行选举,这里拿 3 台服务器进行举例: <table> <thead> <tr> <th>server</th> <th>myid</th> <th>zxid</th> </tr> </thead> <tbody> <tr> <td>zk1</td> <td>1</td> <td>0</td> </tr> <tr> <td>zk2</td> <td>2</td> <td>0</td> </tr> <tr> <td>zk3</td> <td>3</td> <td>0</td> </tr> </tbody> </table> 依次启动 3 台服务器 zk1, zk2, zk3,初始情况下事务 ID 都为 0。 #### 选举大致流程: #### **1、初始投票** 服务器启动后,每个 Server 都会给自己投上一票,每次投票会包含所投票服务器的 myid 和 zxid,这里使用 Server(myid, zxid)的方式表示,此时的投票结果为:zk1(1, 0),zk2(2, 0),zk3(3, 0) **2、同步投票结果** 集群中的服务器在投票后,会将各自的投票结果同步给集群中其他服务器。 **3、检查投票有效性** 各服务器在收到投票后会检查投票的有效性,如:是否本轮投票,是否来自 LOOKING 状态的服务器的投票等。 **4、处理投票** 服务器之间会进行投票比对,规则如下: * 优先检查 zxid,较大的服务器优先作为 Leader * 如果 zxid 相同,则 myid 较大的服务器作为 Leader 如:zk1 和 zk2 进行比对,此时 zk2 胜出,zk1 更新自己的投票为:zk1(2, 0) **5、统计投票结果** 每轮投票比对之后都会统计投票结果,确认是否有超过半数的机器都得到相同的投票结果,如果是,则选出 Leader,否则继续投票。 本轮选举中,zk1 和 zk2 都得到了相同的投票结果(2, 0),2 指 zk2,并且超过了半数的机器(2 > 3 / 2),所以此时 zk2 就成为了本轮选举的 Leader。 所以,即使 zk3 启动了,因为集群已经有了 Leader,所以选举也结束了,zk3 不再参与选举,后面进来的都是小弟。 **6、更改服务器状态** 一旦选出 Leader,每个服务器就会各自更新自己的状态: zk1 >>> FOLLOWING zk2 >>> LEADING Zk3 >>> FOLLOWING ### 2、集群重新选举 ### Zookeeper 集群运行期间无法和 Leader 保持正常连接时,即如果 Leader 挂了,或者 Leader 服务器故障都会进行新一轮的 Leader 选举。 这里还是拿 3 台服务器进行举例: <table> <thead> <tr> <th>server</th> <th>myid</th> <th>zxid</th> </tr> </thead> <tbody> <tr> <td>zk1(Follower)</td> <td>1</td> <td>0</td> </tr> <tr> <td>zk2(Leader)</td> <td>2</td> <td>0</td> </tr> <tr> <td>zk3(Follower)</td> <td>3</td> <td>0</td> </tr> </tbody> </table> 如果作为初始选举的 Leader zk2 挂了,集群就会暂停对外提供服务,从而进行新的 Leader 选举。 #### **选举大致过程:** #### **1、状态变更** 既然过去的老大 Leader 不可用了,那所有的 Follower 服务器就需要从 FOLLOWING 状态变更为:LOOKING,开始新的一轮 Leader 选举。 **2、开始投票** *投票逻辑和启动初始时一致。* zk1, zk3 第一轮投票默认还是会先投给自己,zk2 挂了不能进行投票。 第一轮投票结果为:zk1(1, 66)、zk3(3, 28),zk1 和 zk3 各得一票,这里假设 zk1 事务 ID 比 zk3 更大一点。 **3、同步投票结果** *同步投票逻辑和启动初始时一致。* **4、检查投票有效性** *检查投票逻辑和启动初始时一致。* **5、处理投票** *处理投票逻辑和启动初始时一致。* 此时 zk1 和 zk3 进行比对,根据规则,由于 zk1 的事务 ID 更大一点,所以 zk1 胜出,zk3 也更新自己的投票为:zk3(1, 28) **6、统计投票结果** *统计投票逻辑和启动初始时一致。* 本轮选举中,zk1 和 zk3 都得到了相同的投票结果 zk1,并且超过了半数的机器(2 > 3 / 2),所以此时 zk1 就成为了本轮选举的 Leader。 **7、更改服务器状态** *更改状态逻辑和启动初始时一致。* ## 总结 ## 所以,我们可以总结下,Zookeeper 集群按 myid 从小到大依次启动初始化时,在超过半数机器的投票的情况下,谁的 myid 最大,谁就是 Leader,知道这个定律,不同的集群规模我们都可以推算出谁是 Leader。 **集群初始化时:** 1)集群有 3 台机器,第 2 大的 myid 所在服务器就是 Leader; 2)集群有 4 台机器,第 3 大的 myid 所在服务器就是 Leader; 3)集群有 5 台机器,第 3 大的 myid 所在服务器就是 Leader; 3)集群有 6 台机器,第 4 大的 myid 所在服务器就是 Leader; ..... **集群重新选举时,根据 myid 和 zxid 的大小共同决断,zxid 更大的优先成为 Leader。** 总之,谁得到半数以上的服务器支持,谁就是老大,Zookeeper 选举流程你看懂了吗?这只是粗略版的选举流程,实际选举过程要更复杂,有兴趣的可以深入研究下源码。 好了,今天的分享就到这里了,后面栈长会分享更多好玩的 Java 技术和最新的技术资讯,关注公众号Java技术栈第一时间推送,我也将主流 Zookeeper 面试题和参考答案都整理好了,在公众号后台回复关键字 "面试" 进行刷题。 最后,觉得我的文章对你用收获的话,动动小手,给个在看、转发,原创不易,栈长需要你的鼓励。 > **版权声明:** 本文系公众号 "Java技术栈" 原创,原创实属不易,转载、引用本文内容请注明出处,抄袭者一律举报+投诉,并保留追究其法律责任的权利。 **近期热文推荐:** 1.[1,000+ 道 Java面试题及答案整理(2021最新版)][1_000_ _ Java_2021] 2.[别在再满屏的 if/ else 了,试试策略模式,真香!!][if_ else] 3.[卧槽!Java 中的 xx ≠ null 是什么新语法?][Java _ xx _ null] 4.[Spring Boot 2.5 重磅发布,黑暗模式太炸了!][Spring Boot 2.5] 5.[《Java开发手册(嵩山版)》最新发布,速速下载!][Java] 觉得不错,别忘了随手点赞+转发哦! [1_000_ _ Java_2021]: https://www.javastack.cn/mst/ [if_ else]: https://www.javastack.cn/article/2021/strategy-pattern-instead-of-if-else/ [Java _ xx _ null]: https://www.javastack.cn/article/2021/intellij-idea-ligatures-settings/ [Spring Boot 2.5]: https://www.javastack.cn/article/2021/spring-boot-2.5-released/ [Java]: http://www.javastack.cn/article/2020/alibaba-release-java-develop-rules-songshan/
还没有评论,来说两句吧...