Leader 选举
一个 ZooKeeper 服务要想满足集群方式运行,至少需要三台服务器
集群启动
服务器启动--》网络检查(检查服务器间是否可以通信)--》寻找集群中的 Leader 服务器并进行数据同步等操作
发起通票:发送的服务器的 myid(服务器标识符)和 ZXID (集群投票信息标识符)等选票信息字段都指向本机服务器
接收投票:在接收到网络中的投票信息后,服务器内部首先会判断该条投票信息的有效性。检查该条投票信息的时效性,是否是本轮最新的投票,并检查该条投票信息是否是处于 LOOKING 状态的服务器发出的。
统计投票:主要进行对比的内容是 ZXID,ZXID 数值比较大的投票信息优先作为 Leader 服务器。如果每个投票信息中的 ZXID 相同,就会接着比对投票信息中的 myid 信息字段,选举出 myid 较大的服务器作为 Leader 服务器。
统计集群中服务器的投票结果,判断是否有过半数的机器投出一样的信息。如果存在过半数投票信息指向的服务器,那么该台服务器就被选举为 Leader 服务器。
当 ZooKeeper 集群选举出 Leader 服务器后,ZooKeeper 集群中的服务器就开始更新自己的角色信息,除被选举成 Leader 的服务器之外,其他集群中的服务器角色变更为 Following。
QuorumCnxManager
RecvWorker :接收消息
SendWorker :发送消息
3.4.0后的Zookeeper的版本只保留了TCP版本的FastLeaderElection选举算法
运行时选举
变更状态:当 Leader 服务器崩溃后 ,ZooKeeper 集群中的其他服务器会首先将自身的状态信息变为 LOOKING 状态,该状态表示服务器已经做好选举新 Leader 服务器的准备了,这之后整个 ZooKeeper 集群开始进入选举新的 Leader 服务器过程。
发起投票:首先每个集群中的服务器都会投票给自己,将投票信息中的 Zxid 和 myid 分别指向本机服务器。
接收投票
统计投票
在leader选举期间接收到事务性请求操作的时候,ZooKeeper 服务会先将这个会话进行挂起操作,挂起的会话不会计算会话的超时时间,之后在 Leader 服务器产生后系统会同步执行这些会话操作。
数据同步
为什么要进行数据同步:保证数据的最终一致性
同步条件:首先需要 ZooKeeper 集群中存在用来进行数据同步的 Learning 服务器。
同步过程
务性的会话请求会被同步,而像数据节点的查询等非事务性请求则不在数据同步的操作范围内
同步方式
DIFF 同步:DIFF 同步即差异化同步的方式
TRUNC+DIFF 同步
TRUNC 同步
SNAP 同步
同步后处理:数据同步的本质就是比对 Leader 服务器与 Learning 服务器,将 Leader 服务器上的数据增加到 Learnning 服务器,再将 Learnning 服务器上多余的事物日志回滚
底层实现:Learner.syncWithLeader( )
事务请求处理
zk集群判断是否是事务性请求--》leader服务器处理--》执行请求--》同步数据
setData
预处理阶段:接收网络请求(PrepRequestProcessor )--》验证权限和超时--》封装会话(setDataRequest )--》提交到处理队列(outstandingChanges )
事务处理阶段: 提交、同步、统计
事务执行阶段:将该请求会话的事务头和事务体信息直接交给内存数据库 ZKDatabase 进行事务性的持久化操作
响应客户端:setDataResponse
ZooKeeper 集群在处理事务性请求操作时,要在 ZooKeeper 集群中对该事务性的请求发起投票,只有超过半数的 Follow 服务器投票一致,才会执行该条写入操作。
数据一致性
Leadeer发起事务一致性投票
投票通过
leader执行事务性请求
进行数据一致性操作
LearnerHandler
非事务请求处理
查询会话请求,会将该客户端请求分配给 Follow 服务器进行处理。而在 Follow 服务器的内部,也采用了责任链的处理模式来处理来自客户端的每一个会话请求。
FollowerRequestProcessor
CommitProcessor
选举过程
判断leader失效:Follow 服务器会定期向 Leader 服务器发送 网络请求
重新选举:Follow 服务器的状态变更为 LOOKING 状态
follow角色变更:follow--》leader
数据同步:ZooKeeper 集群在对外提供服务之前,会通过 Leader 角色服务器管理同步其他角色服务器,具体的数据同步方法