ZooKeeper的三个核心选举原则:
(1) Zookeeper集群中只有半数以上的服务器启动,集群才能正常工作(等于半数也不行,因此ZooKeeper集群的服务器最好是奇数台)
(2) 在集群正常工作之前,myid小的服务器给myid大的服务器投票,直到集群正常工作,选出Leader
(3)选出Leader之后,之前的服务器状态由Looking改变为Following,以后的服务器都是Follower
举个例子
我这里有三台服务器:centos01
,centos02
,centos03
这三台服务器上的ZooKeeper的myid
分别为1
,2
,3
接下来进行演示:(注意看我用ssh命令切换到哪个服务器进行的操作)
接下来解释原因:
- 首先启动myid为1的
centos01
上的ZooKeeper,发起一次选举,centos01
先投自己一票,但是由于此时只有一台服务器启动,centos01
票数为1,不够半数(这里为2票),选举无法完成;centos01
的状态为looking
,并且如果此时你用status命令检查centos01
的zk的状态,他会返回一条信息Error contacting service. It is probably not running.
- 接着启动myid为2的
centos02
上的ZooKeeper,发起一次选举,centos01
和centos02
都先分别投自己一票,接着centos01
发现centos02
的myid比自己的大,于是更改自己的选票,改投给centos02
;此时centos02
就有了2票,达到了集群的半数要求,centos02
此时直接变为leader,centos01
的状态也由looking转换为了follower- 接着启动myid为3的
centos03
上的ZooKeeper,即便centos03
的myid大于centos02
上的myid,但是由于centos02
已经确定为leader,因此不会再次举行选举,centos03
直接变为follower- 接下来我们停掉作为leader的
centos02
,由于leader消失,ZooKeeper集群会进行重新选举,存活的centos01
和centos03
分别投给自己一票,接着centos01
发现centos03
的myid比自己的大,于是更改自己的选票,改投给centos03
,此时centos03
就有了2票,达到了集群的半数要求,centos03
因此变为leader,centos01
依旧为follower- 此时如果再停掉follower
centos01
,整个集群只剩下了一台centos03
,并且由于此时集群只有一台服务器存活,达不到半数要求,centos03
自动失去leader地位变为looking状态,此时你用status命令检查centos03
的zk的状态,他也会返回Error contacting service. It is probably not running.
如何自己指定leader
上面的例子里面,无论我们怎么启动停止随便切换,myid为1的centos01
都几乎不可能成为leader,因为他的myid最小。即便当前集群的leader断掉,那么另外一个follower会成为leader,因为二次选举时他的myid值也比centos01
大,centos01
只得把票投给“对手”
若想要
centos01
成功“逆袭”当上leader,那么就需要更改他们的myid值以及zoo.cfg配置文件的server.id值
当前我的三台服务器对应如下:
服务器 | myid |
---|---|
centos01 | 1 |
centos02 | 2 |
centos03 | 3 |
zoo.cfg
配置文件如下:
接下来如果我们将三台服务器的myid对调:
服务器 | myid |
---|---|
centos01 | 3 |
centos02 | 2 |
centos03 | 1 |
并且修改三台服务器上的zoo.cfg
配置文件:
那么结果可想而知:centos03
将几乎永远无法成为leader
此时按顺序依次启动centos01
,centos02
,centos03
再查看他们的状态:
可以看到,centos01
已经变成了leader