zk详解分析

zk3.5之前不支持动态扩容,需要集群停止服务,修改配置文件后重新部署
zk3.5之后支持动态扩容,可以先启动新机器,然后一台一台的重启旧机器即可,保证新增后集群为奇数且重启机器不过半

ServerCnxnFactory/ServerCnxn: 默认NIO实现,用于接收客户端连接,一Accept线程,多Select线程,业务线程池具体处理,
一般流程:NIOServerCnxn.doIO-ZooKeeperServer.processPacket-firstProcessor.processRequest

QuorumVerifier(QuorumMaj): 当前服务器的全局视图(集群里有哪些其他服务器QuorumServer),一般来自配置文件,注意clientAddr,electionAddr,addr(只有自己是Leader才开)

QuorumCnxManager/Listener: 各服务器启动监听自己的electionAddr,一般来说我处于looking-需要选举-发消息给别人-主动连接别人,那么两服务器谁都可能先主动,目前是sid大的连接sid小的端口(接收到sid比自己小的,关闭连接,反向主动连接)
一连接两线程(处理收发),queueSendMap recvQueue

Election(FastLeaderElection):WorkerReceiver线程从qcm获取,若自己looking,放入recvqueue用于选举,若同时对方也looking+对方electionEpoch低,向对方单发,若仅是对方在looking,给出对方我的最终票
WorkerSender线程从sendqueue获取发往qcm

lookForLeader:核心选举流程
electionEpoch/logicalclock 每次选举+1,注意和epoch不一样,epoch集群挂了从磁盘恢复,electionEpoch无法恢复,从0开始
recvset当前electionEpoch的票数(包括自己),outofelection非当前electionEpoch票数
epoch/zxid/sid依次比较决定选择好坏
1 初始选自己,广播
2 循环从recvqueue获取自己+他人的投票,获取不到重新广播或连接,加大超时获取
3 若对方looking,认为集群处于初始状态或leader挂了的情况,大家互相竞争
3.1对方electionEpoch大,更新自己electionEpoch,清空recvset,对方选的比我自己好,我跟票,否则还选我自己,广播
3.2对方electionEpoch小,无效票
3.3electionEpoch相同,对方选的比我选的好,我跟票,广播
3.4选票放入recvset,按照我的选择进行统票,若统票成功(即在此electionEpoch内,有过半的Server包括我自己选的和我一样),则修改自己状态,保存最终票,跳出循环(这里有个最后等待,看是否有更优票)
4 若对方observing,无效票
5 若对方following/leading, 认为现在集群状态是确定的,我应该快速加入
5.1对方electionEpoch相同,按recvset和对方的选择统票,统票成功且也接收到leader的票(票内leader表明自己leading),进入最终流程(状态+最终票+循环)
5.2对方electionEpoch不同,按outofelection和对方的选择统票,统票成功且也接收到leader的票(票内leader表明自己leading),更新自己electionEpoch,进入最终流程

QuorumPeerMain 入口类
QuorumPeerConfig 配置类
QuorumPeer:主要看run方法,选举完毕后,生成Leader或Follower或Observer,并生成对应ZooKeeperServer如LeaderZooKeeperServer
Observer或Follower:discovery-连接到Leader-synchronization-和Leader同步-broadcast-不断接收leader的数据进行处理,注意Observer和Follower的processPacket不同,Observer可以接收写请求
Leader:discovery-打开端口监听连接+waitForEpochAck-synchronization-waitForNewLeaderAck+ZooKeeperServer启动-broadcast-不断ping各Follower和Observer,wait过程保证过半同步后Leader进入broadcast状态,注意每个连接有对应的LearnerHandler线程

举例:Leader接收到write request
ProposalRequestProcessor
1 CommitProcessor放入后返回
2 Leader.propose
3 SyncRequestProcessor(本地写入txnLog,可能导致txnLog滚动和snapshot生成)-AckRequestProcessor(Leader自己也是仲裁一员,把自己ack加上)

Follower(接到propose)-SyncRequestProcessor-SendAckRequestProcessor(发ack)
LearnerHandler(接到ack)-Leader.tryToCommit(过半则Follower commit,Observer inform并加入toBeApplied)-CommitProcessor.commit-ToBeAppliedRequestProcessor(最后进行toBeApplied删除)-FinalRequestProcessor(DataTree.processTxn, 若为客户端请求需应答)

Follower接到commit :CommitProcessor.commit-FinalRequestProcessor
Observer接到inform:SyncRequestProcessor + CommitProcessor.commit-FinalRequestProcessor

举例:observer/follower接收到write request
FollowerRequestProcessor
1 CommitProcessor放入后返回
2 Follower.request-LearnerHandler-ProposalRequestProcessor

存储:
SnapShot(FileSnap):截止到某zxid的全量数据(根据内存数据生成),不断生成快照(理论上之前的就没用了)
TxnLog(FileTxnLog): 事务日志,大小基本固定,不断滚动
SnapShot+TxnLog保证了磁盘数据的完整,FileTxnSnapLog为磁盘访问入口
DataTree为内存的全量数据,ZKDatabase为内存+磁盘的访问入口

IWatchManager: 服务端维护的path和Watcher的多对多关系,
Watcher(ServerCnxn/NIOServerCnxn):代表来自一个客户端的连接/session上的监听
ClientWatchManager(ZKWatchManager):客户端的watch实现

Follower/Observer 和LearnerHandler和Leader的同步流程,以Follower/Observer视角为例:
1 发FollowerInfo/ObserverInfo Leader等待过半FollowerInfo(取各Server的最大epoch+1为new epoch)
2 收LeaderInfo
3 发ACKEPOCH Leader需等过半的ACKEPOCH才会往下走
4 收 DIFF+连续PROPOSAL和COMMIT/SNAP+全量数据/TRUNC(txnlog回走,内存对齐)
5 收NEWLEADER,发ACK, Leader需等过半的ACK才会往下走, 收到UPTODATE
6 发ack
注意:outstandingProposals和toBeApplied也需要发出
三次等待超时都为initLimit,都需等待过半FollowerInfo

1 和leader内存一致或小的不多,diff(内存或txnlog取)
2 比leader内存大,trunc
3 比leader小很多,snap

Leader:半个tickTime全ping一次,一个tickTime检查一次, 某服务器挂了或特别慢(syncLimit未收到任何packet,如回ping),这样的机器达到半数,leader为looking,集群全为looking
注意回ping会带回touchTable,touchTable含两次ping间隔内session对应的客户端的ping信息,Leader可以汇总所有session的信息用于session过期检查

ZookeeperMain 客户端启动类(启动进程,不断接收命令行输入)
Zookeeper(ZookeeperAdmin) 客户端访问入口
ClientCnxn
SendThread 发送,接收,心跳
EventThread watch和异步回调的处理

连接的权限:scheme:expression,通过addAuth添加,存放在内存里,ServerCnxn.authInfo和ClientCnxn.authInfo有
node的权限: scheme:expression:perm,通过setAcl添加,持久化在node的属性里,node的scheme:expression支持更多形式,如下说明
world:anyone(连接的se可以直接通过)
auth:任意字符串(设置权限时用当前连接的权限作为node权限,需考虑AuthenticationProvider.isAuthenticated)
digest:用户密码的复杂处理(连接的se是digest:用户密码明文,最终expression会处理)
连接是否能对node进行某操作:匹配是多对多的,任一能匹配且perm没问题,即权限校验通过

Sequential Consistency - Updates from a client will be applied in the order that they were sent.
Atomicity - Updates either succeed or fail. No partial results.
Single System Image - A client will see the same view of the service regardless of the server that it connects to. i.e., a client will never see an older view of the system even if the client fails over to a different server with the same session.
Reliability - Once an update has been applied, it will persist from that time forward until a client overwrites the update.
Timeliness - The clients view of the system is guaranteed to be up-to-date within a certain time bound.
从单个客户端角度,其写写,写读都是顺序的,failover到其他Server也会校验新Server的zxid大于之前Server的zxid

sync : waits for data to be propagated(sync在CommitProcessor属于needCommit,类似写操作,会阻塞后续的read,Leader在lastProposed得到commit时返回Learner)
瞬态节点不能有children
Set the Java heap size. This is very important to avoid swapping, which will seriously degrade ZooKeeper performance
any uncommitted proposals from a previous epoch seen by a new leader will be committed by that leader before it becomes active
即集群fail,大家都会txnlog内容写入dataTree,然后去竞争leader,这些未正式提交的zxid都会提交

EventType
none(状态变更:客户端与服务端的状态,连接建立,断开,authFail等)(所有watch都能接受到)
数据变更(由服务端发往客户端,部分watch接收)
watchRemove (客户端主动removeWatch,被移除的watch接收)

配置:有的文件配置,有的文件配置或系统属性(文件配置会转成系统属性)
snapCount(100000)+snapSizeLimitInKb(4G) 从上次snapshot后txnLog多少,多大再进行 roll+snapshot
preAllocSize(64M):初始分配大小,后面增长大小
txnLogSizeLimitInKb(默认不开):txnlog文件超过这个,roll,一般设置为N个preAllocSize

4字命令使用的是客户端端口,FourLetterWordMain/telnet可作为4字命令客户端,服务端白名单决定能接收哪些命令
AdminServer(JettyAdminServer)支持4字及其扩展命令

reconfig:不支持并发,一般来说,lastSeenQV和qv是一致的,但是在reconfig的propose到commit期间不一致,lastSeenQV会在propose阶段先改,qv在commit阶段后改,在此不一致期间dynamic.next后缀文件存在
commitAndActivate/informAndActivate为reconfig的commit和inform
reconfig的核心在于修改qv(/zookeeper/config)
reconfig删减了服务器,或新增了服务器但还未调用reconfig:新增或删减的服务器都能正常运行(non-voting follower),只不过不在qv内,即propose的ack不算有效票

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值