1.什么是Zookeeper?
Zookeeper是一个开源的分布式协调服务器框架,由Apache软件基金会开发,专为分布式系统设计。它主要用于在分布式环境中管理和协调多个节点之间的配置信息、状态数据和元数据。
Zookeeper采用了观察者模式的设计理念,其核心职责是存储和管理集群中共享的数据,并为各个节点提供一致的数据视图。在Zookeeper中,客户端(如分布式系统的各个节点)可以注册为“观察者”当这些共享数据发送变化时,Zookeeper会及时通知所有已经注册的观察者,从而使她们能够作出相应的反应或调整。
Zookeeper时一个集中化的服务,用于在分布式系统中实现协调、配置管理、分布式锁、集群管理等功能,确保数据的一致性和可靠性。通过使用Zookeeper,分布式系统中的各个组件能够以一种有序,可控的方式协同工作,从而提高系统的整体稳定性和可用性。
2.zookeeper在分布系统中的角色是?
2.1. 统一命名服务
Zookeeper的统一命名服务类似于域名解析系统。如图所示,假设一个客户端(Client1)需要访问百度,它不直接使用某个特定的IP地址(因为一个服务可能对应多个ip地址,而且这些ip地址可能都是动态变化)。相反,Zookeeper可以通过一个逻辑名称(如www.baidu.com)来统一管理这些ip地址,并将她们映射到实际的服务器节点上。

大致流程:
所有的服务(如百度的多个服务器节点)都会在 Zookeeper 上进行注册。这些服务在注册时会在 Zookeeper 的一个特定目录节点(如/service/www.baidu.com)下创建相应的子节点,并将其 IP 地址(如192.168.30.11、192.168.30.12等)作为子节点的数据存储在zookeeper中。Zookeeper会将所有注册的服务信息存储在统一的命名空间中。
当一个客户端(Client1)需要访问百度时,它不会直接请求具体的 IP 地址。相反,客户端先向 Zookeeper 查询 www.baidu.com 的节点信息。
Zookeeper 会将与 www.baidu.com 关联的所有 IP 地址(例如 192.168.30.11、192.168.30.12、192.168.30.13)作为一个列表返回给客户端。客户端从返回的列表中可以选择一个可用的 IP 地址来访问。
客户端使用从 Zookeeper 获取的 IP 地址列表,随机选择一个或按某种策略选择一个合适的 IP 地址,建立实际的连接请求。这允许客户端访问百度的服务而不必关心底层的实际 IP 地址。
如果百度的某个服务器节点发生变化(例如新增或删除某个 IP 地址),Zookeeper 会自动更新它的命名服务节点。客户端每次请求时,都会得到一个最新的可用 IP 地址列表,从而实现负载均衡和高可用性。
2.2.统一配置管理
在分布式系统(如Kafka、HDFS等)中,所有节点通常需要保持相同或兼容的配置,以确保系统的稳定运行。然而,如果需要手动逐一更新每个节点的配置文件,这将非常麻烦且容易出错。为了解决这个问题,我们可用使用Zookeeper的统一配置管理服务。

大致流程:
在分布式集群中,首先你需要将想要同步的配置文件上传到zookeeper的特定节点(如图中/Configuration)。这个节点将作为统一的配置存储位置,保存最新版本的配置文件内容。
集群中的每个服务器(客户端)会连接到Zookeeper,并向该配置节点(如/Configuration)注册一个Watch(监听器)。当客户端注册成功后,Zookeeper会将当前配置节点的状态返回给客户端,以确保客户端获取到最新的配置文件。
所有注册的客户端持续监控Zookeeper中配置节点的变化。一旦配置文件在Zookeeper中被修改,所有监听该节点的客户端都会收到Zookeeper发送的通知。
Zookeeper在检测到配置节点发送变化时,会立即通知所有注册的客户端。客户端接收到通知后,会立刻知道配置文件已发生更改,准备进行更新操作。客户端接收到通知后,会立刻知道配置文件已发生更改,准备进行更新操作。
每个客户端在收到通知后,主动向Zookeeper请求最新的配置数据(Config Data),并下载该数据。客户端将从 Zookeeper 获取的最新配置数据应用到本地。
客户端使用从 Zookeeper 下载的新配置数据,更新本地的配置文件。完成配置更新后,客户端可以选择重新加载或重启服务以使新的配置生效。
通过这种方式,所有客户端都能够保持与 Zookeeper 中配置文件的一致性,从而确保整个分布式集群中的配置文件同步一致。
2.3.统一集群管理
Zookeeper的统一集群管理通过在节点下为每个客户端创建对应的子节点来监控和管理客户端的状态。这使得分布式集群中的客户端可以实时了解其他客户端的状态,确保系统的高可用性和可靠性。Zookeeper 通过统一管理这些节点,简化了分布式集群的管理和维护工作。

大致流程:
每个客户端(Client1,Client2等)在启动时,会向Zookeeper注册自身的信息。Zookeeper注册自身的信息。Zookeeper 会在指定的节点路径下(如/GroupManager)为每个客户端创建一个子节点(如/GroupManager/client1)这些节点表示每个客户端的存在。
每个客户端节点(如 /client1)不仅表示客户端的存在,还可以存储关于客户端的状态信息(如是否在线、负载情况等)。Zookeeper 可以通过这些节点持续监控每个客户端的状态。
一旦客户端注册成功,Zookeeper 将持续监控这些客户端节点的状态。如果某个客户端的状态发生变化,例如下线或失效,Zookeeper 会更新节点信息,并通知其他相关的客户端。
其他客户端(如 Client2)可以通过 Zookeeper 访问这些节点,获取关于目标客户端的最新状态信息。客户端通过读取 Zookeeper 中的这些节点,能够判断目标客户端的当前状态,从而决定是否发起进一步的操作或访问。
当 Zookeeper 监测到某个客户端的状态发生变化时,会通知所有注册的其他客户端,告知其目标客户端状态的变化。客户端在收到通知后,可以立即采取相应措施,例如重新选择一个可用的客户端进行交互。
2.4.服务器动态上下线

大致流程:
当服务器1、服务器2、服务器3启动时,它们会向Zookeeper集群注册信息(如节点数),并在Zookeeper的特殊节点下创建相应的目录节点(临时节点)。这些节点用于记录各个服务器的状态和当前在线情况。
客户端(Client1、Client2)可以从Zookeeper集群中获取当前在线的服务器列表,并通过监听机制监控这些服务器节点的状态。当客户端注册监听器后,Zookeeper会实时更新客户端关于服务器上下线的动态。
当服务器1下线时,Zookeeper会自动删除其在集群中的临时节点(对应服务器1的信息消失)。因为Zookeeper支持分布式的强一致性,因此这个删除操作会立即通知到所有注册监听该节点的客户端。
收到通知的客户端(Client1、Client2)会了解到服务器1已下线,无法再向服务器1发送请求,并可以选择重新分配请求到其他在线的服务器(服务器2或服务器3)。
2.5.软负载均衡

大致流程:
各个服务器在启动时会向Zookeeper注册自己,Zookeeper在/service节点下为每个服务器创建一个子节点,这些子节点存储每台服务器的访问信息。例如,图片中服务器192.168.30.11注册在Zookeeper中,并记录了其访问次数。
当客户端(如Client1)需要访问某个服务时,它首先会查询Zookeeper中的/service节点,获取所有已注册服务器的列表和相关信息(如访问次数、服务器IP等)
Zookeeper并不直接进行硬件级的负载均衡,而是基于软负载均衡策略。Zookeeper可以将各个服务器的负载信息(如访问次数等)提供给客户端。客户端根据这些信息,选择负载较小的服务器进行访问。例如,当客户端发现192.168.30.11和其他服务器的负载较高时,它可以选择负载相对较低的服务器,如192.168.30.13。
Zookeeper在服务节点的上下线或负载变化时会通知客户端,这使得客户端可以动态地调整访问目标服务器,避免过载。
3.集群模式(Leader-Follower模型)
3.1.第一次启动
Zookeeper 集群中的每个服务器都有一个唯一的 myid(节点 ID),用来区分不同的节点。集群中的所有节点按顺序启动,每个节点都参与 Leader 选举。当服务器启动时,会进行一次Leader 选举。这次选举的目的是确定谁将成为集群的 Leader,负责处理所有的写操作和同步管理。选举过程中,节点会根据 myid 等投票规则来进行投票。(在选取中会遵循过半原则:在选举过程中,集群必须有超过半数的节点投票给同一个候选者,才会确认 Leader。因此,当启动到第三台服务器时(如图中的 server3),由于它得到了集群中过半节点的投票(3票中的2票或更多),server3 会成为集群的 Leader。)
当 server4 和 server5 启动时,它们虽然 myid 更大,但由于 Leader 选举已经完成,并且 Zookeeper 只会在 Leader 出现故障时重新触发选举,因此即便 server4 和 server5 启动,它们仍然会作为 Follower 加入集群,不会改变已有的 Leader(即 server3)。
如果 Leader(如 server3)发生故障或者下线,Zookeeper 会触发新的选举。此时,剩余的服务器将参与重新选举,新的 Leader 将根据当时在线的节点重新选出。在这种情况下,后启动的 server4 和 server5 有可能成为新的 Leader,具体取决于选举结果。
每次写操作都会由 Leader 处理,并为其分配一个唯一的事务 ID(zxid)。该 zxid 包含了时间戳和事务计数,用于确保集群内的操作顺序和一致性。所有的 Follower 节点都会遵循 Leader 的指令,确保数据的一致性。
3.2.非第一次启动
Zookeeper 集群仍然是由上面 5 台服务器组成,当前 server3 是 Leader。当 server3(Leader)和 server5 同时挂掉时,集群剩下的 server1、server2 和 server4 将会重新进行 Leader 选举。如下是 server1、server2 和 server4 具体的信息:
| epoch | zxid | sid | |
| server1 | 1 | 8 | 1 |
| server2 | 1 | 8 | 2 |
| server3 | 1 | 7 | 4 |
选举leader规则优先级如下:epoch>zxid>sid。所以server2被选为leader。



















