【大数据】Zookeeper 集群及其选举机制

news/2025/2/7 4:21:48/

Zookeeper 集群及其选举机制

  • 1.安装 Zookeeper 集群
  • 2.如何选取 Leader

1.安装 Zookeeper 集群

我们之前说了,Zookeeper 集群是由一个领导者(Leader)和多个追随者(Follower)组成,但这个领导者是怎么选出来的呢?我们貌似没有在配置文件中看到有关领导者和追随者的参数啊?

在此之前先来看看 Zookeeper 内部的一些机制:

  • 半数机制:只要有半数以上的节点存活,则集群可用,所以 Zookeeper 集群的节点数量适合为奇数。
  • 虽然在配置文件中没有指定领导者和追随者,但 Zookeeper 在工作时,有一个节点为 Leader,其它则为 Follower,而 Leader 是通过内部的选举机制临时产生的。

那么领导者到底是怎么选出来的呢?很简单,每台服务器都有一个 id(这里的 id 后面说),当启动的服务器超过半数的时候,就会选择 id 最大的 Server 成为领导者。比如有五台服务器,半数就是 2.5 2.5 2.5,因此当启动三台的时候就可以选出领导者。至于剩余的两台,启动之后只能成为追随者,因为领导者已经选出来了。关于这里的细节,一会儿再详细聊。

那么怎么指定服务器的 id 呢?还记得配置文件中的 dataDir 参数吗,在该参数指定的目录下创建一个 myid 文件(文件必须叫这个名字),然后在里面写上服务器的 id 即可。

[root@satori zkData]# echo 2 > myid

这里给 id 设置为 2,因为一会要搭建由三个节点组成的集群,而我希望当前节点成为 Leader,所以它的 id 应该为 2,其它的两个节点的 id 显然分别为 1 和 3。这样按着 id 从小到大的顺序启动时,该节点就会成为 Leader。

下面来我们来搭建 zookeeper 集群,总共三个节点:

  • IP:82.157.146.194,主机名:satori
  • IP:121.37.165.252,主机名:koishi
  • IP:123.60.7.226,主机名:marisa

satori 节点就是当前一直在用的节点,剩余的两个节点的 Zookeeper 也已经安装完毕。那么问题来了,我们要如何将这三个节点组成一个集群呢?显然还需要修改配置文件,先在 satori 节点进行修改。

# koishi 节点
server.1=121.37.165.252:2888:3888
# satori 节点
server.2=0.0.0.0:2888:3888
# marisa 节点
server.3=123.60.7.226:2888:3888

将集群中都有哪些节点写在 zoo.cfg 中,解释一下具体含义,首先两个冒号把等号右边分成了三部分,第一部分就不用说了,IP 地址或者主机名,用于定位节点; 2888 2888 2888 是 Leader 和 Follower 交换信息 的端口,因为副本要进行同步; 3888 3888 3888交换选举信息 的端口,因为要选出 Leader。

然后我们注意到 satori 节点的 IP 设置成了 0.0.0.0,这是因为当前的三个节点不在同一个网段,IP 用的都是公网 IP,而公网 IP 在绑定服务的时候会失败。所以在绑定的时候,其它节点的 IP 要写成公网 IP,自身节点的 IP 要写成 0.0.0.0。因此其它两个节点的 zoo.cfg 文件就应该这么改:

########## koishi 节点配置 ##########
# koishi 节点
server.1=0.0.0.0:2888:3888
# satori 节点
server.2=82.157.146.194:2888:3888
# marisa 节点
server.3=123.60.7.226:2888:3888########## marisa 节点配置 ##########
# koishi 节点
server.1=121.37.165.252:2888:3888
# satori 节点
server.2=82.157.146.194:2888:3888
# marisa 节点
server.3=0.0.0.0:2888:3888

但是在 生产中,一个集群内的节点应该都位于同一网段,然后将配置文件中的 IP 全部换成内网 IP 即可。这样彼此之间可以通过内网访问,而内网的访问速度要远远快于公网,并且还不需要走公网的流量。但我当前的三台云服务器不在同一个网段,所以只能用公网 IP,并且绑定的时候,将节点自身的 IP 换成 0.0.0.0

至于等号左边的 server. 是固定的,后面的数字表示节点的 id,而节点 id 我们说了,通过在 myid 文件中进行指定。而节点 id 决定了,最终由谁担任领导者。其中 satori 节点的 id 2 2 2,刚刚已经改过了,然后将 koishimarisa 两个节点的 id 分别改为 1 1 1 3 3 3,然后就大功告成了。

然后我们来启动 Zookeeper,由于 satori 节点的 Zookeeper 已经启动了,我们在修改完配置文件之后,需要重新启动。

在这里插入图片描述

但是我们查看状态的时候,发现出错了,相信原因很好想。因为配置文件中指定了三个节点,而剩余两个节点的 Zookeeper 还没启动。下面我们来启动一下,然后再次查看状态。

在这里插入图片描述

当剩余的两个节点启动之后,再次查看状态,发现 Mode 变成了 Leader。显然集群已经启动成功,至于剩余的两个节点,显然就是 Follower。

在这里插入图片描述
在这里插入图片描述
此时集群就启动成功了,但是关于领导者和追随者的选举问题,我们还得再说一说。

2.如何选取 Leader

领导者选举分为两种情况:

  • 集群第一次启动的时候,选举领导者。
  • 运行过程中领导者挂了,从追随者当中选择一个作为领导者。

我们先来看第一种情况,假设集群当中有 5 个节点,id 分别为 1 到 5,来看看选举过程是怎样的?这里 5 个节点按照 id 从小到大顺序启动。
在这里插入图片描述

  • 首先 server1 启动,发起一次选举,每个节点都有投票权,并且默认都会投给自己。此时 server1 1 1 1 票,但还不够半数以上( 3 3 3 票),选举无法完成,于是 server1 将状态保持为 LOOKING
  • 然后 server2 启动,再发起一次选举,重新投票。server1server2 仍会把票投给自己,然后再交换选票信息。由于 server1 发现 server2id 比自己大,于是会将自己的票改投给 server2。此时 server1 0 0 0 票,server2 2 2 2 票,但仍然没有哪个节点拥有超过半数的票,选举无法完成,server1server2 状态都保持为 LOOKING
  • 接下来 server3 启动,再发起一次选举,相信整个过程不需要解释了。老规矩还是先投给自己,再交换选票信息,然后 server1server2 发现自己的 id 都没有 server3 大,于是都会将票改投给 server3。此时 server1server2 的票数为 0 0 0server3 的票数为 3 3 3,由于 server3 的票数已超过半数,所以成功当选为 Leader,状态变为 LEADING。而 server1server2 则成为 Follower,状态改为 FOLLOWING
  • 所以 5 5 5 个节点,启动 3 3 3 个之后就能选择出 Leader。然后 server4 又启动了,于是也发起一次选举,并把票投给自己。但 server1server2server3 已经不是 LOOKING 状态,所以它们不会更改自己的选票信息,最终结果 server3 仍有 3 3 3 票,server4 只有 1 1 1 票。少数服从多数,于是会再将自己的选票交给 server3,成为 Follower,状态改为 FOLLOWING
  • 同理,最后 server5 启动,结果就是 server3 4 4 4 票,自己只有 1 1 1 票。少数服从多数,于是将自己的选票交给 server3,成为 Follower。

所以整个过程,关键点有两个

  • 每个 server 启动之后都会发起选举,并将票投给自己。然后交换选票信息,并将票投给 id 最大的 server
  • 一旦选择出 Leader,其它节点自动成为 Follower。而后启动的 server,不论 id 多大,也只能成为 Follower。

以上就是集群第一次启动的时候,选举领导者。

但如果在运行过程中,领导者挂了该怎么办呢?显然要再选举出一个新的领导者。所以当集群中的追随者发现自己连接不上领导者的时候,就会开始进入 Leader 选举,但此时是存在两种可能的。

  • 领导者真的挂了。
  • 领导者没有挂,只是追随者因为某些原因无法和领导者建立连接。比如 server5 发现连接不上 server3 了,于是它认为领导者挂了,便开启 Leader 选举。但事实上 server3 并没有挂,其它追随者都能正常连接,只是 server5 因为某些原因连接不上罢了。

先来解释第二种情况,server5 认为 server3 挂了之后,便会发起 Leader 选举,呼吁其它追随者进行投票。但是其它追随者发现领导者并没有挂,于是会拒绝 server5 的选举申请,并告知它当前已存在的领导者信息。对于 server5 而言,只需要和已存在的领导者重新建立连接,并进行数据同步即可。

server3:老子还没挂呢!!!😤

但如果是第一种情况,领导者真的挂了,该怎么办?比如这里的领导者 server3,在运行的时候,节点突然宕机了。

要解释这个问题,我们需要引入一些新的概念。

  • sid:就是我们一直说的服务器 id,用于唯一标识集群中的节点。
  • zxid:事务 id,客户端在发起一次写请求的时候,都会带有 zxid,用于标识一次服务器状态的变更。所以 Zookeeper 也是有事务的,保证每次写数据的时候,要么全部写完,要么不写,不会出现只写一半的情况。另外每个节点都有自己的 zxid,它们的值也不一定相同。
  • epoch:Leader 任期的编号,就好比古代皇帝,每个皇帝在当政的时候都有自己的年号。并且每投完一次票,这个编号就会增加。

现在假设 server3 挂了,那么要重新选举 Leader,而选举规则如下:

  • 先比较节点之间的 epochepoch 大的直接当选。
  • epoch 相同,再比较 zxidzxid 大的当选。
  • epochzxid 都相同,则比较 sidsid 大的当选。

关于这么做背后的原理,我们先暂且不表,等到后面介绍 Paxos 协议的时候再细说。而且这里的 epoch 具体是干什么用的,估计也有人不太清楚,这些我们也留到后面再说。


http://www.ppmy.cn/news/1295117.html

相关文章

MongoDB主从仲裁模式安装

MongoDB主从仲裁模式安装 环境介绍 操作系统 : CentOS release 6.8 (Final) Master IP : 10.4.19.83 Arbiter IP : 10.104.27.126 Slave IP : 10.104.27.126 安装文件 : mongodb-linux-x86_64-rhel62-4.4.9.tgz …

2023-编程语言的发展历史与发展新趋势

一、引言 编程语言作为构建数字化世界的基石,始终保持着持续创新和变革。从20世纪50年代的第一代编程语言,到如今的众多编程语言家族,编程语言的发展历程见证了人类科技的飞速进步。本文将探讨编程语言发展历史与发展新趋势,分析…

SQL 在已有表中修改列名的方法

文章目录 1. MySQL2. SQL Server3. Oracle / PostgreSQL Question: 假设有一张表 StudentInfo,表中有一个列名是 Student_Name ,想要把这个列名改成 StudentName 应该如何操作? 建表语句如下: --建表 if object_id(S…

分布式数据之复制(Replication)

1.简介 1.1简介——使用复制的目的 在分布式系统中,数据通常需要被分散在多台机器上,主要为了达到以下目的: 扩展性,数据量因读写负载巨大,一台机器无法承载,数据分散在多台机器 上可以有效地进行负载均衡…

香橙派5b 移植 imx415

香橙派5b 移植 imx415 镜头配置 Sensor选用如下型号:香橙派OrangePi_5 RK3588S IMX415 我使用的时候更换了镜头,将该sensor装在了我的变焦780模组上,经过后续测试因为CAM1相对稳定,所以安装在CAM1。安装位置如下: 配…

springboot第47集:【思维导图】面向对象,关键字,标识符,变量,数组的使用...

关键字:class,public,static,void等,特点是全部关键字都是小写字母。 image.png image.png 凡是自己起的名字可以叫标识符 image.png image.png image.png image.png 整数类型的使用 image.png image.png image.png 浮点类型 image.png image.png 字符类…

PHP运行环境之宝塔Web站点部署

目录 Web站点部署流程(部署聚合支付后台) 项目文件 将上传的文件解压文件至根目录 修改站点关键信息 设置伪静态,选择:thinkphp,并保存 设置PHP,选择:70+版本即可。 安装网站 1设置运行目录

MySQL之视图内连接、外连接、子查询

目录 一、视图 1.1 含义 2.1 视图的基本语法 二、案例 三、思维导图 一、视图 1.1 含义 虚拟表,和普通表一样使用 视图(view)是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据…