1 环境搭建
1.1 zoo.cfg配置
tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
# 集群中的follower服务器(F)与leader服务器(L)之间 初始连接 时能容忍的最多心跳数(tickTime的数量)
# 当超过设置倍数的 tickTime 时间,则连接失败
initLimit=5
# 集群中的follower服务器(F)与leader服务器(L)之间 请求和应答 之间能容忍的最多心跳数(tickTime的数量)
# 如果 follower 在设置的时间内不能与leader 进行完成通信,那么此 follower 将被丢弃
syncLimit=2
# 配置组成集群的zk服务器节点
# server.X:server固定写法,X服务器的myid标识
# zookeeper01:节点地址或者域名
# 2888:Follower与集群中的Leader服务器交换信息的端口
# 3888:执行Leader选举时服务器相互通信的端口
# observer:标记为observer角色节点
server.1=zookeeper01:2888:3888
server.2=zookeeper02:2888:3888
server.3=zookeeper03:2888:3888
server.4=zookeeper04:2888:3888;
server.5=zookeeper05:2888:3888;
server.6=zookeeper06:2888:3888;observer
1.2 节点标识文件
- 文件位置:%%dataDir%%/myid
- 文件内容:一个数字,server.X中的X要跟这个数字保持一致
1.3 安装过程
1.1、1.2做完后,拷贝三份分别放到三台服务器上,并修改myid中的信息,然后依次启动服务
2 集群相关概念
2.1 集群角色
- Leader:为客户端提供读服务和写服务。
- Follower:提供读服务,参与Leader 的选举过程。
- Observer:提供读服务,不参与 Leader 的选举过程,也不参与写操作的"过半写成功"策略,因此 Observer 可以在不影响写性能的情况下提升集群的读性能。
2.2 服务状态
- LOOKING 不确定Leader状态。该状态下的服务器认为当前集群中没有Leader,会发起Leader选举。
- FOLLOWING 跟随者状态。表明当前服务器角色是Follower,并且它知道Leader是谁。
- LEADING 领导者状态。表明当前服务器角色是Leader,它会维护与Follower间的心跳。
- OBSERVING 观察者状态。表明当前服务器角色是Observer,与Folower唯一的不同在于不参与选举,也不参与集群写操作时的投票。
2.3 其他信息
SID:服务器ID。用来唯一标识一台ZooKeeper集群中的机器,每台机器不能重
复,和myid一致。
ZXID:事务ID。ZXID是一个事务ID,用来标识一次服务器状态的变更。在某一时刻,
集群中的每台机器的ZXID值不一定完全一致,这和ZooKeeper服务器对于客户端“更
新请求”的处理逻辑有关。
Epoch:每个Leader任期的代号。没有Leader时同一轮投票过程中的逻辑时钟值是
相同的。每投完一次票这个数据就会增加
3 选举机制
假设我需要构建一个5个节点的Zookeeper服务,基本信息如下图所示。
什么时候会开始进行leader选举呢?
- 服务器第一次启动。
- 服务器运行期间无法和Leader保持连接。
3.1 服务器第一次启动
- 服务器1启动,发起一次选举。服务器1投自己一票。此时服务器1票数一票,不够半数以上(3票),选举无法完成,服务器1状态保持为LOOKING;
- 服务器2启动,再发起一次选举。服务器1和2分别投自己一票并交换选票信息:此时服务器1发现服务器2的myid比自己目前投票推举的(服务器1)大,更改选票为推举服务器2。此时服务器1票数0票,服务器2票数2票,没有半数以上结果,选举无法完成,服务器1,2状态保持LOOKING
- 服务器3启动,发起一次选举。此时服务器1和2都会更改选票为服务器3。此次投票结果:服务器1为0票,服务器2为0票,服务器3为3票。此时服务器3的票数已经超过半数,服务器3当选Leader。服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING;
- 服务器4启动,发起一次选举。此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息。交换选票信息结果:服务器3为3票,服务器4为1票。此时服务器4服从多数,更改选票信息为服务器3,并更改状态为FOLLOWING;
- 服务器5启动,同4一样当小弟。
3.2 服务器运行期间无法和Leader保持连接
当一台机器进入Leader选举流程时,当前集群也可能会处于以下两种状态:
- 集群中本来就已经存在一个Leader。
对于第一种已经存在Leader的情况,机器试图去选举Leader时,会被告知当前服务器的Leader信息,对于该机器来说,仅仅需要和Leader机器建立连
接,并进行状态同步即可。 - 集群中确实不存在Leader 。
假设集群正常运行后,某一时刻3和5服务器出现故障,剩下1、2和4三台服务器,超过半数,有条件选举出新的leader,因此开始进行Leader选举。选举Leader 的规则如下:
①EPOCH大的直接胜出
②EPOCH相同,事务id大的胜出
③事务id相同,服务器id大的胜出
4 脑裂问题
- 什么叫脑裂
脑裂问题:所谓的“脑裂”即“大脑分裂”,也就是本来一个“大脑”被拆分了两个或多个“大脑”。通俗的说,就是比如当你的 cluster 里面有两个节点,它们都知道在这个 cluster 里需要选举出一个 master。那么当它们两之间的通信完全没有问题的时候,就会达成共识,选出其中一个作为 master。但是如果它们之间的通信出了问题,那么两个结点都会觉得现在没有 master,所以每个都把自己选举成 master,于是 cluster 里面就会有两个 master。 - Zookeeper是如何解决脑裂问题的?
Zookeeper为解决脑裂问题,要求集群内的节点数量为奇数个,即2N+1, 当网络分裂后,始终有一个集群的节点数量过半数,而另一个集群节点数量小于N+1(即小于半数), 因为选主需要过半数节点同意,所以任何情况下集群中都只有一个leader,这样就避免了脑裂问题。