服务器各角色
leader
- 事务请求的唯一调度和处理者,保证集群事务处理的顺序性。(事务请求个人理解其实就是写请求)。
- 集群内部各个服务器的调度者(管理follower,数据同步)。
- 将自己写完的数据,同步给follower和abserver
follower
- 处理非请求事务,转发事务请求给leader
- 参与事务请求prososal投票
- 参与leader选举投票
observer
- 处理非事务请求,转发事务请求给leader
- 只为了扩展系统存在,提高读写速度
observer存在的意义是什么:
他存在的意义必然是因为他不参与投票的特殊性。为什么zk要单独拎出来一个不投票的服务器呢。
原因在于zk的分布式一致性协议,当事务请求commit的时候,需要超过半数的投票,才能进行commit,投票的机器数量越多,网络消耗就越大。所以就需要一种不需要参与投票的,只负责读请求的机器,来缓解集群读请求压力,这种服务器就是observer。
所以,zk中一共有两种投票。
- leader选举投票
- 事务请求commt投票
leader选举
leader选举的触发条件
- 服务器初始化启动。也就是刚组成集群的时候。
- 服务器运行期间无法和leader保持连接。也就是leader挂了。
zk在正常运行过程中,一旦选出了leader,这个leader就不会变化了,即使有新的机器加入集群,即使有非leader机器挂了。只有leader自己挂了,才会开始leader选举。
leader是干嘛的,选leader有什么用
- 分布式一致性。只让leader自己处理写请求,然后将写的数据,同步给从(在分布式协议中细讲)。
- 恢复数据
- 发起投票,更新系统状态
术语解释
术语 | 解释 |
---|---|
SID:服务器ID | SID是一个数字,唯一标识一个zookeeper服务器 |
ZXID:事务ID | 唯一标识一次服务器状态的变更。在某一个时刻,集群中每台机器的ZXID不一定全都一致,为什么????在主从同步先回滚再差异化同步策略中会讲 |
Vote:投票 | leader选举,必须通过投票来实现。当集群中的机器发现自己无法检测到leader机器的时候,就会开始尝试进行投票 |
Quorum:过半机器数 | 可以把这个术语理解为一个量词,如果集群中总的机器数是n,那么Quorum=(n/2 + 1),总数是3,Quorum就是2。 |
vote的数据结构
属性 | 说明 |
---|---|
id | 被推举的leader的SID |
zxid | 被推举的leader的事务ID |
electionEpoch | 逻辑时钟,用来判断多个投票是否在通一轮选举周期中。该值再服务端是一个自增序列。每次进入新的一轮投票后,都会对该值进行+1 |
peerEpoch | 被推举的leader的epoch |
state | 当前服务器的状态 |
服务器状态
状态 | 说明 |
---|---|
looking | 寻找leader状态。当服务器处于该状态时,它会认为当前集群中没有leader,因此需要进入leader选举流程 |
following | 跟随者状态,表明该服务器的角色是leader |
leading | 领导者状态,表明该服务器的角色是leader |
observing | 观察者状态,表明该服务器的角色是observer |
laader选举
选举的原则:
- 谁ZXID大,选谁。(最新的session)
- ZXID一样大,谁SID大选谁。
开始第一次投票
投票中包含了两个最基本的信息:所推举服务器的SID和所推举服务器的ZXID。以(SID, ZXID)表示。举例,如果当前服务器要推举SID为1,ZXID为8的服务器成为leader,那么它这次投票信息可以表示为(1,8)。
注:第一次投票,都是投给自己。
现在假设zk由5台机器组成,SID分别为1,2,3,4,5,ZXID分别为9,9,9,8,8。并且此时leader是SID为2的机器。某一时刻1和2出现故障,开始进行leader选举
在第一次投票的时候,都投自己。3投(3,9),4投(4,8),5投(5, 8)
投票变更
集群中每台机器发出自己的投票后,也会接收其他机器的投票。
收到其他机器的(SID, ZXID)后,都会跟自己的(SID, ZXID)比较。按照选举规则。
- server3,收到(4,8)和(5,8),自己是(3,9),先比ZXID,自己是9,最大,不变更,将(3,9)发出去。
- server4,收到(3,9)和(5,8),因为9比自己大,变更投票为(3,9),将这个变更投票发出去。
- server5,收到(3,9)和(4,8),因为9比自己大,变更投票为(3,9),将这个变更投票发出去。
确定leader
经过第二次投票后,集群中的每台机器又会收到其他所有机器的投票,这个时候就要计算了票数了。
只要有一台机器收到了超过半数的相同的投票,那么这个投票对应的SID机器即为leader。
本例子中,每台服务器会收到两次(3,9)的投票,所以server3当选leader。
leader选举技术细节QuorumCnxManager:网络I/O
zk处理所有选举相关网络连接。就是这个QuorumCnxManager。
在每台服务器启动的时候,都会启动一个QuorumCnxManager,负责各台服务器之间的leader选举过程中的底层网络通信。
QuorumCnxManager维护了一系列的消息队列,用于保存接收到的、待发送的消息,以及消息的发送器。
属性 | 解释 |
---|---|
recvQueue | 消息接收队列,用于存放那些从其他服务器收到的消息 |
sendQueue | 消息发送队列,用于存放待发送的消息 |
queueSendMap | 消息发送队列,用于保存那些待发送的消息。它是一个map,按照SID分组,分别为每台机器分配一个单独的队列,从而保证各台服务器之间的消息发送互不影响 |
senderWorkerMap | 发送器集合。也是按照SID进行分组。每个senderWorker发送器,都对应一台zk服务器,负责消息的发送。 |
lastMessageSent | 最近发送过的消息。在这个集合中,为每个SID保存最近发送过的一个消息 |
workerReceiver | 选票接收器。该数据会不断的从QuorumCnxManager接收其他服务器的选举消息,并转换成自己最终的投票(根据选举规则),然后保存到recvQueue队列中。如果发现该外部投票的轮次小于当前服务器,忽略这个投票。如果发现这个投票来自observer,也忽略该投票 |
网友评论