zookeeper选举源码流程图
2021-08-20 18:02:22 14 举报
zookeeper选举流程,致敬大师,致敬未来的你。
作者其他创作
大纲/内容
false
处理选票
更新选票,哪个胜出更新成谁的
快速选举
WorkerReceiver.run()
启动内部的JettyServer,通过这个Sever可以获取到各种节点状态信息,可以用来作运维观察服务信息的入口
sidself.getId
queuedPackets.add(p);
readPacket(QuorumPacket pp)
默认NIO,官方推荐Netty
启动当前线程run
protocolVersion = din.readLong()//实际上是获取到当前机器的sid
序列化接收到的消息
发送选票
是
while循环发送选票
super.startup();
WorkerSender.run()
核心启动流程开始
发送消息是从全局的map中通过sid找到对应的消息队列,这个队列中的消息会在快速选举的时候生成,如果没有线程会accept
for(ids){connectOne()}
启动服务
Vote current = self.getCurrentVote();
New font color=\"0\
run
wrThread.start()
更新自己的选举周期 logicalclock.set(n.electionEpoch);清空选票箱recvset.clear();
FastLeaderElection.lookForLeader()
QuorumPeer.run
连接主节点
loadDataBase()
判断收到的选票当中的选票周期n.electionEpoch和自己本身机器的选票周期logicalclock.get()
ReciverWork.run()
LearnerCnxAcceptor.run()
listener.start()
QuorumPeerConfig.parse
启动接收线程
线程执行
sendqueue.offer(notmsg);
ServerCnxnFactory.createFactory
给其它节点发送自己的选票
Listner.run
父类启动线程
读取接收的消息
判断从接收队列里面是否拿到了选票
startZkServer();
switch (getPeerState())
break
接收方的选票胜出更新自己机器的选票信息
true,重新进行选票pk流程
添加到接收队列
this.mySid == sid
启动本地jetty服务
处理连接
new QuorumPeer()
LOOKING
ss = new ServerSocket()ss.bind(addr);client = ss.accept();
QuorumPeerMain.initializeAndRun
SenderWork.run()
更新当前线程名称(QuorumPeer[myid=%d](plain=%s)(secure=%s))
直接扔到接收队列里面
发送选票信息
QuorumPacket qp = new QuorumPacket(); while (this.isRunning()) { readPacket(qp); processPacket(qp); }
FOLLOWING
启动选举流程
判断socket连接中数据流的sid和当前机器的sid的大小
sid=self.getId
updateThreadName()
构造心跳消息
接收的是前面初始化的线程
添加到心跳队列
设置Quorumpeer信息:quorumPeer.setElectionType(config.getElectionAlg());//选举算法quorumPeer.setMyid(config.getServerId()); //服务IdquorumPeer.setConfigFileName(config.getConfigFilename());//配置文件quorumPeer.setZKDatabase(newZKDatabase(quorumPeer.getTxnFactory())); //设置内存数据库(数据节点类型)…
Boolean.getBoolean(\"readonlymode.enabled\")//判断是集群启动还是单机启动
for (LearnerHandler f : getLearners(){ f.ping();}
pk选票逻辑:1.先比较选举周期,接收的选票选举周期大返回true; 2.再比较zxid,接受的大返回true 3.最后比较sid,如果接受的sid大返回true对于sid为0的机器来讲,选举周期和zxid都是一样的,后加来的如果机器id大就选票胜出
如果接收到的选票信息是LOOKING并且选举周期小于自己的选举周期
从队列获取选票
s = ss.accept();
判断选票的Id是否是当前机器的id
开启快速选举流程
验证是否合法的机器选票
follower.followLeader();
BinaryInputArchive.readRecord()
currentVote = newfont color=\"0\
adminServer.start()
解析配置文件加载到内存
接收数据线程启动
recvqueue.offer(n);
处理线程启动
死循环接收leader数据
如果本机的sid和投的leader是一样的,那么自己就是leader;否则自己的角色是Follewer或者是Oberver
font color=\"0\
getQuorumPeerMain.getQuorumPeer
registerJMX();
选举周期+1
socket连接
初始化选举管理器
n.electionEpoch=logicalclock.get()
setLeader(makeLeader(logFactory));
super.start
启动发送器线程
cnxAcceptor.start();
集群启动
获取leaderder的信息
ReadOnlyZooKeeperServer.startup()
生成选票
执行follower逻辑
setState(State.RUNNING);
根据前面设置的NIO或者Netty来确定不同的启动方式
notifyAll();
validVoter(response.sid)
快速选举算法实现
接收的选票周期大于自己的选票周期这种情况一般就是自己可能由于断网重新参与选举或者自己后加入集群参与选举,但是这个时候其它机器已经参与过好几轮选举了
sidself.getId,如果当前机器的sid大于socket中的sid
构造处理链条
connectOne(sid)
ReadOnlyZooKeeperServer.run()
zk.startup();
获取发送选票的机器ID
for(sids){sendqueue.offer(notmsg);}
self.setPeerState((proposedLeader == self.getId()) ?ServerState.LEADING: learningState());
和所有的follower建立心跳
DatadirCleanupManager.start
recvQueue.add(msg);
如果被选举出来成为leader,那么leader的角色会收发读写请求,或者收到选举然后告诉leader的地址等
manager.connectAll();第一次选票就是空的,所以需要建立连接,外面while循环会再次判断当前拿到的选票是不是null
this.messenger.start()
syncWithLeader(newEpochZxid);
ArrayBlockingQueue<ByteBuffer> bq = queueSendMap.get(sid);send(b)
计算选票票数是否过半
startLeaderElection()
sendNotifications();
启动发接收器线程
加载数据
receiveConnection(client)
从队列中取出选票
初始化Leader
同步leader数据
sendNotifications();
setCurrentVote(makeLEStrategy().lookForLeader());
根据当前节点状态while循环处理业务
wsThread.start()
监听选举端口,使用普通的ServerSocket(BIO)
初始化选举流程时候会初始化两个队列,一个是发送选票的队列,一个是接受选票的队列
开始选举算法
finally:setFollower(null);updateServerState();设置自己的状态为looking,继续下一轮的选举
setFollower(makeFollower(logFactory));
否
leader.lead();
判断是不是选举状态
catch exception
否,本机已经不是选举状态了会获取当前机器的记录leader的选票消息
放入选票集合
注册JMS
启动
new ServerSocekt监听其它folloing节点的数据同步端口
和所有的serverId建立连接
false,设置自己的角色
此处会将快照和日志信息的数据加载到DataTree的内存数据源结构中
启动选举端口
添加到选票队列
是,本机处于LOOKING选举状态
更新选票数据
FOLLOWING,LEADING 这种状态一般是集群中已经选举出来了leader,后加入进来的机器处于looking状态,对于后加入进来的机器直接则会将leader的选票发送给新机器,新机器直接设置成Follower或者Oberver
启动server端的服务
startServerCnxnFactory()
LEADING
pk选票
启动发送线程
runFromConfig(config)
QuorumServer leaderServer = findLeader();
此处如果不是选举状态会将选举状态中认为是leader的选票信息发送给对方
LearnerHandler.run()
清空接收队列返回leader选票
zk.loadData();
setupRequestProcessors();
createElectionAlgorithm(electionType)
secureCnxnFactory.start()
执行leader逻辑
switch (n.state)判断发送方选票的状态
true,过半数了,判断能否从接收队列拿到消息
如果要用netty通信需要加上启动参数:Dzookeeper.serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory
startSessionTracker()
启动自动清理快照任务
n.electionEpochlogicalclock.get()
n.electionEpochlogicalclock.get()s新加入的机器选举周期小于当前机器的选举周期那么说明选票无效
单机启动
读取配置文件设置节点信息
处理接收的数据
quorumPeer.start()
ss = new ServerSocket() ss.bind(self.getQuorumAddress());
ManagedUtil.registerLog4jMBeans
接收客户端连接
n==null
建立连接
加载快照文件
process(m);
self.getPeerState() == QuorumPeer.ServerState.LOOKING
logicalclock.incrementAndGet()
createCnxnManager()
0 条评论
回复 删除
下一页