1、Zookeeper选举机制

假设我们有一个由五台服务器组成的ZooKeeper集群,这些服务器的ID分别是1到5。这些服务器都是全新启动的,没有历史数据,因此在存放数据量的初始状态上,它们都是相同的。现在,我们按照ID的顺序依次启动这些服务器,让我们看看会发生什么。
image.png

(1)当服务器1启动时,由于此时集群中只有它一台服务器,它发出的通信请求没有任何响应。因此,服务器1无法找到其他服务器进行协作,其选举状态将保持为LOOKING状态,表示它正在寻找可以与之形成集群的其他服务器。

(2)随后,服务器2启动并尝试与服务器1进行通信。两者互相交换各自的选举信息,由于它们都没有历史数据,因此选举将基于服务器的ID进行。在这个例子中,服务器2的ID值较大,因此它在这次局部选举中胜出。然而,由于集群中尚未有超过半数(在这个例子中为3台或更多)的服务器同意选举服务器2为领导者,因此服务器1和服务器2都将继续保持LOOKING状态,继续等待其他服务器的加入和进一步的选举。

(3)当服务器3启动并加入到集群中时,它开始与服务器1和服务器2进行通信并参与到选举过程中。根据ZooKeeper的选举机制,服务器3将成为服务器1、2、3中的领导者,因为它是一个新加入的服务器,并且基于其ID和集群当前的选举状态,它可以被其他服务器所接受。此时,由于有三台服务器(服务器1、2、3)都选举了服务器3作为领导者,达到了集群中超过半数的支持,因此服务器3成功当选为这次选举的领导者。

(4)当服务器4启动时,它尝试与集群中的其他服务器通信并参与选举。虽然服务器4的ID在服务器1、2、3、4中是最大的,但由于在服务器4加入之前,已经有超过半数的服务器(服务器1、2、3)选举了服务器3作为领导者,因此服务器4无法改变现有的选举结果。服务器4将接受服务器3作为领导者,并成为集群中的一个跟随者(Follower)。

(5)最后,当服务器5启动时,它也会经历类似的过程。服务器5将尝试与集群中的其他服务器通信并参与选举,但由于服务器3已经被选举为领导者,并且得到了足够多的支持,服务器5将接受这一结果并成为集群中的另一个跟随者。


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

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

在ZooKeeper中,服务器与客户端之间建立的是一个持久的长连接。这个连接在SESSION_TIMEOUT指定的时间段内保持活跃,期间服务器会检查客户端是否正常连接。客户端会定期向服务器发送心跳(heart_beat)以保持连接的活性,并且每次成功发送心跳后,服务器会重置下一个SESSION_TIMEOUT的计时。只要这个过程正常进行,Session就会一直有效,并且ZooKeeper集群中的所有机器都会保存这个Session的信息。

然而,在某些情况下,客户端与服务器之间的连接可能会断开。这可能是因为客户端所连接的ZooKeeper服务器宕机了,或者由于其他原因导致的网络临时中断。在这种情况下,客户端并不会立即放弃,而是会在它初始化时提供的地址列表(connectString)中选择一个新的地址尝试重新连接。

在这个过程中,用户可能会遇到两种异常:CONNECTIONLOSS(连接断开)和SESSIONEXPIRED(会话过期)。CONNECTIONLOSS表示客户端与ZooKeeper服务器之间的连接暂时丢失,但会话可能仍然有效。在这种情况下,用户不需要担心会话的状态,因为客户端库会尝试自动重连到ZooKeeper集群中的其他服务器。

一旦客户端成功连接到新的ZooKeeper服务器,它会检查之前提交的操作是否已成功执行。这是因为ZooKeeper的设计保证了即使在连接中断的情况下,已经提交的事务也会被安全地处理。因此,即使用户遇到了CONNECTIONLOSS异常,他们通常也不需要采取任何额外的措施,除非有特定的业务需求需要处理这种异常情况。

需要注意的是,如果连接断开的时间超过了SESSION_TIMEOUT设定的阈值,那么ZooKeeper服务器会认为客户端已经死亡,会话将会过期,此时客户端会收到SESSIONEXPIRED异常。在这种情况下,客户端需要重新建立会话并恢复之前的状态。

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