问题1:zookeeper是用来干嘛的?
答案:zookeeper是一个分布式锁的框架,提供了诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知和分布式锁等分布式基础服务。
Zookeeper 有三种运行模式:单机模式、伪集群模式和集群模式。
- 单机模式:这种模式一般适用于开发测试环境,一方面我们没有那么多机器资源,另外就是平时的开发调试并不需要极好的稳定性。
- 集群模式:一个 ZooKeeper 集群通常由一组机器组成,一般 3 台以上就可以组成一个可用的 ZooKeeper 集群了。组成 ZooKeeper 集群的每台机器都会在内存中维护当前的服务器状态,并且每台机器之间都会互相保持通信。
- 伪集群模式:这是一种特殊的集群模式,即集群的所有服务器都部署在一台机器上。当你手头上有一台比较好的机器,如果作为单机模式进行部署,就会浪费资源,这种情况下,ZooKeeper 允许你在一台机器上通过启动不同的端口来启动多个 ZooKeeper 服务实例,以此来以集群的特性来对外服务。
问题2:zookeeper集群的工作模式?
答案:zookeeper集群的工作模式是主从模式、读写分离,集群中有三种角色:领导者、跟随者、观察者。
- 领导者(leader):负责进行投票的发起和决议,更新系统状态。
- 跟随者(follower):用于接收客户端请求并给客户端返回结果,在选主过程中进行投票。
- 观察者(observer):可以接受客户端连接,将写请求转发给 leader,但是observer 不参加投票的过程,只是为了扩展系统,提高读取的速度。
问题3:zookeeper集群模式中主节点发生问题之后如何进行集群的崩溃恢复,也就是说怎么选举产生新的主节点?
答案:zookeeper在集群崩溃恢复时采用自身定义的一个协议叫ZAB协议,这个协议的详细内容和过程相对其他的主从模式的选主过程比较复杂。ZAB协议包括两个内容,一个是崩溃恢复,一个是数据同步
ZAB协议的崩溃恢复:
leader选举
如果 leader 选举算法能够保证新选举出来的 Leader 服务器拥有集群中所有机器最高编号(ZXID最大)的事务 Proposal,那么就可以保证这个新选举出来的 Leader 一 定具有已经提交的提案。因为所有提案被 COMMIT 之前必须有超过半数的 follower ACK,即必须有超过半数节点的服务器的事务日志上有该提案的 proposal,因此, 只要有合法数量的节点正常工作,就必然有一个节点保 存了所有被 COMMIT 消息的 proposal 状态
关于ZXID
ZXID 其实就是事务id,为了保证事务的顺序一致性,zookeeper 采用了递增的事务 id 号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加上了 zxid。
ZXID是64位的数字,高32位是epoch编号,低32位是消息计数器:
- 高32位:epoch(ZAB协议通过epoch 编号来区分 Leader 周期变化的策略),用来标识 leader 关系是否改变,每次一个 leader 被选出来,所有结点的新 epoch=原来的epoch+1(初始值=1)。
可以理解成,标识当前属于那个leader的统治时期,保证了即使旧leader恢复后也没有人再听它的(数据同步后就成了follower),因为 follower 只听从当前年代的 leader 的命令。 - 低32位:用于递增计数,每接收到一条消息这个值+1。新 leader选举后这个值重置为0。
这样设计的好处在于老的leader挂了以后重启,它不会被选举为 leader,因此此时它的 zxid 肯定小于当前新的 leader。当老的 leader 作为 follower 接入新的 leader 后,新的 leader 会让它将所有的拥有旧的 epoch 号的未被 COMMIT 的 proposal 清除
在同一epoch下,通过对比新提案的ZXID与自身最新ZXID是否相差“1”,来保证事务严格按照顺序生效的。
服务器启动时的 leader 选举
每个节点启动的时候状态都是 LOOKING,处于观望状态,接下来就开始进行选主流程。
若进行 Leader 选举,则至少需要两台机器,这里选取 3 台机器组成的服务器集群为例。在集群初始化阶段,当有一台服务器 Server1 启动时,其单独无法进行和完成 Leader 选举,当第二台服务器 Server2 启动时,此时两台机器可以相互通信,每台机器都试图找到 Leader,于是进入 Leader 选举过程。选举过程如下:
(1) 每个 Server 发出一个投票。由于是初始情况,Server1 和 Server2 都会将自己作为 Leader 服务器来进行投票,每次投票会包含所推举的服务器的 myid 和 ZXID、epoch,使用(myid,ZXID,epoch)来表示, 此时 Server1 的投票为(1, 0),Server2 的投票为(2, 0),然后各自将这个投票发给集群中其他机器。
(2) 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票(epoch)、是否来自 LOOKING 状态的服务器。
(3) 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行 PK,PK 规则如下:
i. 优先比较 epoch;
ii. 其次检查 ZXID。ZXID 比较大的服务器优先作为 Leader;
iii. 如果 ZXID 相同,那么就比较 myid。myid 较大的服务器作为
Leader 服务器。
对于 Server1 而言,它的投票是(1, 0),接收 Server2 的投票为(2, 0), 首先会比较两者的 ZXID,均为 0,再比较 myid,此时 Server2 的 myid 最大,于是更新自己的投票为(2, 0),然后重新投票,对于 Server2 而言,其无须更新自己的投票,只是再次向集群中所有机器发出上一次投票信息即可。
(4) 统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于 Server1、Server2 而言,都统计出集群中已经有两台机器接受了(2, 0)的投票信息,此时便认为已经选出了 Leader。
(5) 改变服务器状态。一旦确定了 Leader,每个服务器就会更新自己的状态,如果是 Follower,那么就变更为 FOLLOWING,如果是 Leader, 就变更为 LEADING。
运行过程中的 leader 选举
当集群中的 leader 服务器出现宕机或者不可用的情况时,那么整个集群将无法对外提供服务,而是进入新一轮的 Leader 选举,服务器运行期间的 Leader 选举和启动时期的 Leader 选举基本过程是一致的。
(1) 变更状态。Leader 挂后,余下的非 Observer 服务器都会将自己的服务器状态变更为 LOOKING,然后开始进入 Leader 选举过程。
(2) 每个 Server 会发出一个投票。在运行期间,每个服务器上的 ZXID 可能不同,此时假定 Server1 的 ZXID 为 123,Server3 的 ZXID 为 122; 在第一轮投票中,Server1 和 Server3 都会投自己,产生投票(1, 123), (3, 122),然后各自将投票发送给集群中所有机器。接收来自各个服务器的投票。与启动时过程相同。
(3) 处理投票。与启动时过程相同,此时,Server1 将会成为 Leader。
(4) 统计投票。与启动时过程相同。
(5) 改变服务器的状态。与启动时过程相同.
Dcoker安装zookeeper集群:
dcoker安装zookeeper集群相对比较容易一些,docker容器相当于多个不同的单机,所以zookeeper的模式属于是就去那模式。
首先要有一台安装了docker的linux的服务器,安装集群模式要大于等于3台才可以,其他的分布式集群模式同样也需要大于等于3台,这样才可以适用集群的一些机制。
1、首先我们需要拉取镜像:docker pull zookeeper:3.5.8
2、查看镜像:docker images
3、集群模式部署,可以通过docker-compose的方式来启动,首先我们需要安装docker-compose安装过程可以百度其他方法,有可能需要安装或者更新pip等或者直接下载安装到解压也可以,总之是可以成功安装docker-compose。然后新建dcoker-compose.yml文件。
vi docker-compose.yml 输入以下内容:
services:
zoo1:
image: zookeeper:3.5.8
restart: always
hostname: zoo1
ports:
- 2181:2181
environment:
ZOO_MY_ID: 1
ZOO_SERVERS: server.1=0.0.0.0:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181
zoo2:
image: zookeeper:3.5.8
restart: always
hostname: zoo2
ports:
- 2182:2181
environment:
ZOO_MY_ID: 2
ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=0.0.0.0:2888:3888;2181 server.3=zoo3:2888:3888;2181
zoo3:
image: zookeeper:3.5.8
restart: always
hostname: zoo3
ports:
- 2183:2181
environment:
ZOO_MY_ID: 3
ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=0.0.0.0:2888:3888;2181
4、输入之后键盘esc退出编辑模式,:wq保存并退出
然后再当前目录下执行:docker-compose up -d
5、查看当前容器:docker ps
6、成功安装了集群模式的3台zookeeper
7、安装之后我们需要查看一下当前3台中,哪一个是leader,进入其中一个容器
docker exec -it zookeeper_zoo1_1 /bin/bash 红色部分是容器名或者容器ID
8、进入容器的bin目录,看到zkServer.cmd是windows下的命令,zkServer.sh是Linux下的命令
9、执行:./zkServer.sh status ,可以看zoo3这台是leader,配置文件是/conf/zoo.cfg
10、打开查看一下配置文件:cat /conf/zoo.cfg
关于zookeeper的极少和安装先到此结束,欢迎大家批评指正!