Zookeeper

58 阅读5分钟

简述ZooKeeper的选举机制

5台服务器组成的zookeeper机器,id从1-5,都是最新启动的,也没有历史数据在存放数据量这一点上,都是一样的,服务器依次启动看看会发生什么

1)服务器1启动,此时只有它一台服务器启动了,它发出去的报没有任何相应,所以它的选举状态一直是LOCKING状态
2)服务器2启动,它与最开始启动的1进行通信,互相交换自己的选举结果,由于两者都没有历史数据,所以id值较大的服务器2胜出,但是由于没有达到超过半数以上的服务器同意选举它,所以服务器1、2 还是继续保持Looking状态
3)服务器3启动 根据前面的理论分析,服务器3成为1,2,3中的leader,而与上面不同的是,此时有三台服务器选举了它,所以它成为这次选举的Leader.
4)服务器4启动,根据前面的分析,理论上服务器是1、2、3、4中最大的,但是由于前面已经有半数以上的服务器选举了服务器3,所以它成为Follower
5)服务器5启动,同4一样成为Follower.

注意,如果按照5,4,3,2,1的顺序启动,那么5将成为Leader,因为在满足半数条件后,Zookeeper集群启动,5的id最大被选举为Leader

客户端对Zookeeper的 ServerList的轮询机制

客户端在初始化的过程中,将所有Server保存在一个List中,然后随机打散,形成一个环,之后从0号位开始一个一个使用。
两个注意点:
Server地址能够重复配置,这样能够弥补客户端无法设置Server权重的缺陷,但是也会加大风险
如果客户端在进行Server切换过程中耗时过长,那么将会收到SESSION_EXPIRED.这也是上面第1点中加大风险之处。

客户端如何正确处理CONNECTIONLOSS(连接断开)和SESSIONEXPIRED(session过期)两类连接异常

在Zookeeper中,服务器和客户端之间维持的是一个长连接,在SESSION_TIMEOUT时间内,服务器会确定客户端是否正常连接(客户端会定时向服务器发送heart_beat)服务器重置下次SESSION_TIMEOUT时间。因此在正常情况下,Session一直有效,并且ZK集群所有机器上都保存这个Session信息。在出现问题的情况下,客户端与服务器之间连接断了(客户端所连接的那台Zk机器挂了,或是其它原因网络闪断),这个时候客户端会主动在地址列表(初始化的时候传入构造方法的那个参数connectString)中选择新的地址进行连接
以上即为服务器与客户端之间维持长连接的过程,在这个过程中,用户可能会看到两类异常CONNECTIONLOSS(连接断开)和SESSIONEXPIRED(Session过期)
发生CONNECTIONLOSS后,此时用户不需要关心我的会话是否可用,应用所要做的就是等待客户端帮我们自动连接上新的Zk机器,一旦成功连接上新的Zk机器后,确认之前的操作是否执行成功了;

一个客户端修改了某个节点的数据,其他客户端能够马上获得这个最新数据吗?

Zookeeper不能确保任何客户端能够获取(即Read Request)到一样的,除非客户端自己要求,方法是客户端在获取数据之前调用org.apache.zookeeper.AsyncCallbak k.VoidCallback,java.lang.Object)sync
通常情况下(指 1:对获取数据是否是最新版本不敏感,2.一个客户端修改了数据,其他客户端是否需要立即能够获取最新数据,可以不关心这点)

Zookeeper对节点的Watch监听是永久的吗?为什么?

不是。
一个Watch事件是一个一次性的触发器,当被设置了Watch的数据发生了改变的时候,则服务器将这个改变发送给设置了Watch的客户端,以便通知它们

为什么不是永久的,举个例子,如果服务端变动频繁,而监听的客户端很多情况下,每次都要通知所有的客户端,这态小号性能了

一般是客户端执行getData("/节点A",true),如果节点A发生了变更或删除,客户端会得到它的Watch事件,但是在之后的节点A又发生了变更,而客户端有没设置watch事件,就不再给客户端发送
在实际应用中 许多情况下,客户端不需要服务端的每一次变动,只要最新的数据即可

Zookeeper中使用watch的注意事项有哪些?

使用watch需要注意的几点:
Watches通知是一次性的,必须重复注册
发生CONNECTIONLOSS之后,只要在session_timeout之内再次连接上(即不发生SESSIONEXPIRED)那么这个连接注册的watches依然在
节点数据的版本变化会触发NodeDatachanged,注意这里特意说明了是版本变化。存在这样的情况,只要成功执行了setData()方法,无论内容是否和之前一致,都会触发NodeDataChanged