目录
基本概念解释:
1. Leader
2. Follower
3. Observer
4. Learner
5. Client
角色对比
ZOOKEEPER选举过程:
1. 快速Leader选举(Fast Leader Election)
选举过程:
特点:
2. 基于TCP的Leader选举
选举过程:
特点:
zxid和myid
myid
zxid
1. zxid 的集群共有性
2. 为什么每个服务器有自己的 zxid?
3. zxid 的生成和同步
4. 选举过程中 zxid 的作用
5. 为什么需要比较本地 zxid?
基本概念解释:
在介绍选举leader之前,先来介绍一下什么是zookeeper:
ZooKeeper是一个开源的分布式应用程序协调服务,来自于Google的Chubby一个开源的实现。是Hadoop和Hbase的重要组件。Zookeeper可以为分布式应用提供一致性的服务,功能包括:配置维护、名字服务、分布式系统、组服务等等。Zookeeper的目标是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。ZooKeeper包含一个简单的原语集,提供Java和C的接口。
ZOOKEEPER的角色:
角色 | 描述 | 职责 |
---|---|---|
Leader | 集群中的主节点,负责处理写请求和事务协调。 | - 处理客户端的写请求。 - 广播事务(PROPOSAL)给Follower。 - 提交事务(COMMIT)。 - 维护集群的事务顺序(zxid)。 |
Follower | 集群中的从节点,负责处理读请求和同步Leader的数据。 | - 处理客户端的读请求。 - 参与事务投票(ACK)。 - 同步Leader的数据。 - 参与Leader选举。 |
Observer | 类似于Follower,但不参与事务投票,用于扩展读性能。 | - 处理客户端的读请求。 - 同步Leader的数据。 - 不参与事务投票和Leader选举。 |
Learner | 泛指Follower和Observer,表示从Leader学习数据的节点。 | - 从Leader同步数据。 - 根据角色(Follower/Observer)决定是否参与投票。 |
Client | 客户端,与ZooKeeper集群交互,发送读/写请求。 | - 发送读请求(任意节点)。 - 发送写请求(必须由Leader处理)。 |
1. Leader
-
作用:Leader是集群的核心节点,负责处理所有写请求和事务协调。
-
职责:
-
接收客户端的写请求,并将其转换为事务。
-
广播事务(PROPOSAL)给所有Follower。
-
收集Follower的确认(ACK),并在达到Quorum后提交事务(COMMIT)。
-
维护全局的事务顺序(通过zxid)。
-
-
特点:
-
集群中只有一个Leader。
-
如果Leader崩溃,会触发新的Leader选举。
-
2. Follower
-
作用:Follower是集群中的从节点,负责处理读请求和同步Leader的数据。
-
职责:
-
处理客户端的读请求。
-
参与事务投票(ACK),确认是否接受Leader广播的事务。
-
同步Leader的数据,保持与Leader的一致性。
-
参与Leader选举,投票选出新的Leader。
-
-
特点:
-
可以处理读请求,减轻Leader的负载。
-
参与事务投票和Leader选举,是集群的重要组成部分。
-
3. Observer
-
作用:Observer类似于Follower,但不参与事务投票,用于扩展集群的读性能。
-
职责:
-
处理客户端的读请求。
-
同步Leader的数据,保持与Leader的一致性。
-
不参与事务投票和Leader选举。
-
-
特点:
-
不参与投票,因此不会影响写性能。
-
主要用于扩展读性能,适合读多写少的场景。
-
4. Learner
-
作用:Learner是Follower和Observer的统称,表示从Leader学习数据的节点。
-
职责:
-
从Leader同步数据。
-
根据角色(Follower/Observer)决定是否参与投票。
-
-
特点:
-
Learner是一个抽象概念,用于描述Follower和Observer的共同行为。
-
5. Client
-
作用:客户端是与ZooKeeper集群交互的应用程序。
-
职责:
-
发送读请求(可以直接发送给任意节点)。
-
发送写请求(必须发送给Leader,或由Follower转发给Leader)。
-
-
特点:
-
客户端通过ZooKeeper提供的API与集群交互。
-
客户端可以连接到任意节点(Leader/Follower/Observer)。
-
角色对比
特性 | Leader | Follower | Observer | Client |
---|---|---|---|---|
处理读请求 | 是 | 是 | 是 | 发送读请求 |
处理写请求 | 是 | 转发给Leader | 转发给Leader | 发送写请求 |
参与事务投票 | 是(发起投票) | 是(ACK确认) | 否 | 否 |
参与Leader选举 | 是(被选举) | 是(投票) | 否 | 否 |
数据同步 | 是(广播数据) | 是(同步数据) | 是(同步数据) | 否 |
数量 | 1(集群中只有一个Leader) | 多个 | 多个 | 多个 |
ZOOKEEPER选举过程:
1. 快速Leader选举(Fast Leader Election)
快速Leader选举是ZooKeeper默认的选举算法,基于**Zab协议(ZooKeeper Atomic Broadcast)**实现。它的核心思想是通过投票机制快速选出一个Leader,确保集群的高效性和一致性。
选举过程:
-
初始状态:
-
每个ZooKeeper服务器启动时处于LOOKING状态,表示正在寻找Leader。
-
-
投票:
-
每个服务器会投票给自己,投票信息包括:
-
myid:服务器的唯一标识。
-
zxid:服务器上最新的事务ID(越大表示数据越新)。
-
epoch:选举轮次。
-
-
服务器将投票信息广播给集群中的其他服务器。
-
-
比较投票:
-
每个服务器收到其他服务器的投票后,会比较投票信息:
-
优先比较zxid,zxid越大,优先级越高。
-
如果zxid相同,则比较myid,myid越大,优先级越高。
-
-
-
更新投票:
-
如果收到的投票比自己当前的投票更优,服务器会更新自己的投票,并重新广播。
-
-
确定Leader:
-
当某个服务器收到超过半数的相同投票(即Quorum),它会确定投票中的服务器为Leader,并将自己的状态改为FOLLOWING。
-
被选中的服务器将自己的状态改为LEADING,成为Leader。
-
特点:
-
快速:通过优先比较zxid和myid,快速选出Leader。
-
高效:避免了复杂的协商过程,适合大规模集群。
2. 基于TCP的Leader选举
基于TCP的Leader选举是ZooKeeper早期版本中使用的一种选举方式,现在已经较少使用。它的核心思想是通过TCP连接和简单的投票机制选出Leader。
选举过程:
-
初始状态:
每个服务器启动时处于LOOKING状态。 -
建立连接:
每个服务器尝试与其他服务器建立TCP连接。 -
投票:
每个服务器投票给自己,并将投票信息发送给其他服务器。 -
比较投票:
服务器收到其他服务器的投票后,会比较投票信息(基于myid和zxid)。 -
确定Leader:
当某个服务器收到超过半数的相同投票时,它会确定投票中的服务器为Leader。
特点:
-
简单:实现较为简单,适合小规模集群。
-
效率较低:依赖TCP连接的建立和维护,选举速度较慢。
zxid和myid
myid
myid是在zookeeper在初始化集群时写在配置文件中的,是每个服务器的唯一标识,是一个整数。
如在zoo.cfg中配置:
server.1=192.168.1.1:2888:3888
server.2=192.168.1.2:2888:3888
server.3=192.168.1.3:2888:3888
对应的myid分别是1 2 3
myid用于区分集群中不同的服务器,在选举过程中,如果两个服务器的zxid相同,则会比较myid,myid更大的服务器优先级更高。
zxid
zxid是zookeeper的事务id,用于标识事务的顺序。它由Leader产生,是集群中唯一的标识事务的量。
如何产生:zxid由两部分组成:epoch和counter
epoch:表示Leader的任期。每次选举新的Leader时,epoch会递增。
counter:表示事务的序号,每次新的事务发生时,counter会递增。
在每个服务器启动时,会从本地磁盘加载最新的zxid(既最后一次提交的事务)
如果服务器是第一次启动,或者没有历史数据,则zxid为0
这里就会说,欸,比较时每个服务器发送zxid,但是这个参数又是集群共有的,那如何比较呢?
这其实是一种误解,具体解释如下:
1. zxid 的集群共有性
-
zxid 是集群共有的:在ZooKeeper集群中,所有服务器最终会达成一致,拥有相同的 zxid。这是因为ZooKeeper通过 Zab协议(ZooKeeper Atomic Broadcast) 保证所有服务器按相同的顺序执行事务。
-
zxid 的一致性:一旦一个事务被提交(即被大多数服务器确认),所有服务器都会看到相同的 zxid。
2. 为什么每个服务器有自己的 zxid?
尽管 zxid 是集群共有的,但在选举过程中,每个服务器会携带自己本地的 zxid,这是因为:
-
数据同步的延迟:在分布式系统中,不同服务器之间的数据同步可能存在延迟。某些服务器可能已经收到了最新的事务,而其他服务器还没有。
-
本地 zxid 的作用:每个服务器的本地 zxid 表示它当前已经提交的最新事务。在选举过程中,这个值用于比较服务器的数据新旧程度。
3. zxid 的生成和同步
-
Leader 生成 zxid:只有Leader可以生成新的 zxid。当Leader接收到一个新的事务请求时,它会递增 zxid 的低32位(counter),并将事务广播给所有Follower。
-
Follower 同步 zxid:Follower接收到Leader广播的事务后,会按照 zxid 的顺序执行事务,并更新自己的本地 zxid。
4. 选举过程中 zxid 的作用
在选举过程中,每个服务器会携带自己本地的 zxid,用于比较数据的新旧程度。具体过程如下:
-
初始状态:
-
每个服务器启动时,会从本地磁盘加载最新的 zxid。
-
如果服务器是第一次启动,或者没有历史数据,则 zxid 为
0
。
-
-
投票:
-
每个服务器投票给自己,并携带自己的 myid 和 zxid。
-
-
比较投票:
-
服务器收到其他服务器的投票后,会比较 zxid:
-
zxid 越大的服务器,数据越新,优先级越高。
-
如果 zxid 相同,则比较 myid,myid 越大的服务器优先级越高。
-
-
-
确定Leader:
-
当某个服务器收到超过半数的相同投票(即Quorum),它会确定投票中的服务器为Leader。
-
5. 为什么需要比较本地 zxid?
-
确保数据一致性:通过比较 zxid,可以确保选举出的Leader拥有最新的数据,从而避免数据丢失或不一致。
-
处理网络分区:在网络分区的情况下,某些服务器可能无法与Leader通信,导致它们的 zxid 落后于其他服务器。通过比较 zxid,可以确保选举出的Leader是最新的。
如此在回头看选举过程,就会明朗的多。如果文章帮到了你,请帮主播点个小关小猪哦~~