正文
一、传统方式安装
1、下载安装包
https://dlcdn.apache.org/zookeeper/zookeeper-3.7.0/apache-zookeeper-3.7.0-bin.tar.gz
2、将下载好的tar.gz包上传服务器,解压缩
tar -zxvf apache-zookeeper-3.7.0-bin.tar.gz -C /usr/local/
3、进入/usr/local/目录更换名字
[root@localhost local]# mv apache-zookeeper-3.7.0-bin zookeeper
4、进入zookeeper文件,创建data和logs文件夹
[root@localhost local]# cd zookeeper/ [root@localhost zookeeper]# mkdir data [root@localhost zookeeper]# mkdir logs [root@localhost zookeeper]#
5、更换zoo_sample.cfg名字为zoo.cfg
[root@localhost zookeeper]# cd conf/ [root@localhost conf]# mv zoo_sample.cfg zoo.cfg [root@localhost conf]#
6、编辑zoo.cfg文件添加如下内容(vim编辑 :wq保存退出)
dataDir =/usr/local/zookeeper/data dataLogDir=/usr/local/zookeeper/logs #ip对应的是你的ip server.1=192.168.6.137:2888:3888 server.2=192.168.6.138:2888:3888 server.3=192.168.6.139:2888:3888
7、修改data文件
[root@localhost conf]# cd ../data/ #在这个文件里输入1 [root@localhost data]# vim myid [root@localhost data]# cat myid 1 [root@localhost data]#
8、将此虚拟机赋值两份,另外两台机器分别修改myid为2和3。
9、分别启动三台
1. [root@localhost data]# cd ../bin/ 2. [root@localhost bin]# ./zkServer.sh start
二、Docker安装Zookeeper
1、搜索镜像文件
[root@localhost bin]# docker search zookeeper
2、下载镜像(apach)
[root@localhost bin]# docker pull zookeeper
3、创建挂载文件
mkdir -p /data/zookeeper/{conf,data,logs}
4、启动
docker run --name zookeeper -d -p 2181:2181 -v/data/zookeeper/conf/zoo.cfg:/conf/zoo.cfg -v/data/zookeeper/data:/data -v/data/zookeeper/logs:/logs zoozookeeper
5、docker -ps检查容器是否启动成功
三、Docker安装Zookeeper集群
就Docker而言,桥接网络使用软件桥接器,该软件桥接器允许连接到同一桥接网络的容器进行通信,同时提供与未连接到该桥接网络的容器的隔离。Docker桥驱动程序会自动在主机中安装规则,以便不同桥接网络上的容器无法直接相互通信。就是说我们建立三个节点的话,zk之间是无法获取到彼此的节点的。
1、搭建Docker桥接网络
[root@localhost ~]# docker network create --driver bridge --subnet=172.18.0.0/16 --gateway=172.18.0.1 zoonet 1e88b597e707a19fba03a4368e553289de3e410dd587b8faef7780aebd9149b1
[root@localhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 3ae0cb2e611a bridge bridge local b8fccf7a64a2 host host local 6fed61369952 none null local 1e88b597e707 zoonet bridge local
2、创建挂载目录
mkdir /data/zookeeper/cluster/zk1/{data,datalog,logs} -p mkdir /data/zookeeper/cluster/zk2/{data,datalog,logs} -p mkdir /data/zookeeper/cluster/zk3/{data,datalog,logs} -p
3、启动节点
节点1
docker run -d -p 2181:2181 --name zookeeper_node01 --privileged --restart always --network zoonet --ip 172.18.0.2 \ -v /data/zookeeper/cluster/zk1/data:/data \ -v /data/zookeeper/cluster/zk1/datalog:/datalog \ -v /data/zookeeper/cluster/zk1/logs:/logs \ -e ZOO_MY_ID=1 \ -e "ZOO_SERVERS=server.1=172.18.0.2:2888:3888;2181 server.2=172.18.0.3:2888:3888;2181 server.3=172.18.0.4:2888:3888;2181" zookeeper
节点2
docker run -d -p 2182:2181 --name zookeeper_node02 --privileged --restart always --network zoonet --ip 172.18.0.3 \ -v /data/zookeeper/cluster/zk2/data:/data \ -v /data/zookeeper/cluster/zk2/datalog:/datalog \ -v /data/zookeeper/cluster/zk2/logs:/logs \ -e ZOO_MY_ID=2 \ -e "ZOO_SERVERS=server.1=172.18.0.2:2888:3888;2181 server.2=172.18.0.3:2888:3888;2181 server.3=172.18.0.4:2888:3888;2181" zookeeper
节点3
docker run -d -p 2183:2181 --name zookeeper_node03 --privileged --restart always --network zoonet --ip 172.18.0.4 \ -v /data/zookeeper/cluster/zk3/data:/data \ -v /data/zookeeper/cluster/zk3/datalog:/datalog \ -v /data/zookeeper/cluster/zk3/logs:/logs \ -e ZOO_MY_ID=3 \ -e "ZOO_SERVERS=server.1=172.18.0.2:2888:3888;2181 server.2=172.18.0.3:2888:3888;2181 server.3=172.18.0.4:2888:3888;2181" zookeeper
如下图
4、查看docker 日志
docker logs -f 1912ae817d33
5、停止删除所有镜像
docker stop $(docker ps -a -q) docker rm $(docker ps -a -q) #批量停止容器 docker stop $(docker ps -a | grep "xxx" | awk '{print $1}')
6、进入容器检验
[root@bogon conf]# docker container exec -it a819ee7874b4 /bin/bash root@a819ee7874b4:/apache-zookeeper-3.7.0-bin# cd bin/ root@a819ee7874b4:/apache-zookeeper-3.7.0-bin/bin# ./zkServer.sh status ZooKeeper JMX enabled by default Using config: /conf/zoo.cfg Client port found: 2181. Client address: localhost. Client SSL: false. Mode: leader root@a819ee7874b4:/apache-zookeeper-3.7.0-bin/bin#
搭建成功
四、Zookeeper选举
启动选举
在集群初始化阶段,当有一台服务器Server1启动时,其单独无法进行和完成Leader选举,当第二台服务器Server2启动时,
两台机器此时可以相互通信,每台机器都试图找到Leader,于是进入选举过程。
选举过程如下:
(1)每个Server发出一个投票,由于是初始情况,Server1和server2都会将自己作为Leader服务器来进行投票。
每台服务器会往其他服务器发送投票信息,这个投票信息包括了SID和ZXID,其中SID就是该台机器的唯一标识(myid);
ZXID是事务id,该ID是64位的,分为高32位和低32位。
(2)由于是初次投票,此时的ZXID相同,所以比较的就是SID,SID越大,获得的Leader的可能越大(为了严谨,
本文针对任何情况都只说可能,不说绝对)。
(3)两台服务器发出自己的投票信息后,再根据自己收到的其他服务器的投票信息决定自己的投票信息是否变更,第一台服务器SID为1,第二台服务器SID为2,所以Server2的投票变更为2,
即有两票,由于一共三台服务器,此时Server2已经处于半数以上,所以决定出来的Leader为Server2;(半数投票)即使Server3启动,
由于Leader已经决定出来,所以不需要在进行投票,Server3只需要与Leader建立连接并进行状态同步即可。
宕机选举
假如此时有5台服务器,并且已经选举出Server3作为Leader,突然Leader(Server3)宕机,那么此时其他四台服务器要进行重新选举,
它们便会进入LOOKING状态。
(1)在运行期间,它们的ZXID可能不会相同,于是再新一轮的Leader选举中,不仅仅需要比较SID(myid),还要比较ZXID,ZXID越大(在zk每次提交事务时,zxid相应的增加,所以认为zxid越大,数据越新),选举成Leader的可能越大。
(2)在初次选举中我们可以得出一个结论,便是SID(myid)位于中间,选举出Leader的可能性最大。但在运行时Leader突然宕机,再次进行选举时,这种结论已经不适用了,有可能选举出的Leader是Server1,也有可能是Server2,或者是Server4、Server5。
(3)值得注意的一点是,刚刚说了ZXID越大,选举出Leader的可能越大,前面说过ZXID分为高32位和低32位,ZXID中的低32位相比较的话,低32位越小的一方得到的Leader的可能性越大。
2、每台机器发出投票后,也会接受到其他机器的选举,每台机器会根据一定的规则来处理收到的其他机器的投票信息,与自己进行对比。
这个规则是整个Leader选举算法的核心所在。其中术语描述如下:
vote_sid:接收到的投票中所推举Leader服务器的SID(myid)。
vote_zxid:接收到的投票中所推举Leader服务器的ZXID。
self_sid:当前服务器自己的SID(myid)。
self_zxid:当前服务器自己的ZXID。
每次对收到的投票的处理,都是对(vote_sid,vote_zxid)和(self_sid,self_zxid)对比的过程。
规则一:如果vote_zxid大于self_zxid,就认可当前收到的投票,并再次将该投票发送出去。
规则二:如果vote_zxid小于self_zxid,那么坚持自己的投票,不做任何变更。
规则三:如果vote_zxid等于self_zxid,那么就对比两者的SID,如果vote_sid大于self_sid,那么就认可当前收到的投票,并再次将该投票发送出去。
规则四:如果vote_zxid等于self_zxid,并且vote_sid小于self_sid,那么坚持自己的投票,不做任何变更。
参考:
基于Docker进行Zookeeper集群的安装 - wellDoneGaben - 博客园