
ZooKeeper原理与源码
文章平均质量分 90
ZooKeeper原理与源码
东阳马生架构
回归初心,保持好奇心,享受那些"成功解题"的喜悦~
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
zk源码-7.ZAB协议和数据存储二
数据快照本质上就是将内存中的所有节点信息和会话信息保存到磁盘中,所以会先通过ZKDatabase的getDataTree()方法获取到DataTree,然后再通过ZKDatabase的getSessionWithTimeOuts()方法获取会话信息。此时已基于数据快照文件构建了一个完整的DataTree实例和Session集合,所以接着会根据这个数据快照文件的文件名来解析出一个最新的ZXID。由于每个数据快照文件中的所有内容都是有效的,因此数据快照文件的大小能一定程度反映当前zk内存中全量数据的大小。原创 2025-04-13 22:26:03 · 590 阅读 · 0 评论 -
zk源码—7.ZAB协议和数据存储一
这个Leader会检查事务日志:如果发现自己事务日志里有一个还没进行提交的Proposal提议,那么就说明旧Leader没来得及发送Commit消息就崩溃了,此时它作为新Leader会为这个Proposal提议向Follower发送Commit消息,从而保证旧Leader提交的事务最终可以被提交到所有Follower中。如果Proposer收到半数以上Acceptor,对其发出的编号为M的Prepare请求的响应,那么它就会发送一个针对[M, V]提案的Accept请求给半数以上的Acceptor。原创 2025-04-13 22:25:25 · 1045 阅读 · 0 评论 -
zk源码—6.Leader选举的实现原理二
在此过程中,如果发现其他服务器发来的投票的选举轮次小于当前服务器,那么就直接忽略这个其他服务器发来的投票,同时立即发出自己的投票。一旦zk服务器发现针对当前远程服务器的消息发送队列为空,那么就从lastMessageSent中取出一个最近发送的消息进行再次发送,以此解决上次发送的消息没有被接收到和没有被正确处理的问题。如果统计投票发现已经有过半的服务器认可了当前的投票,那么zk并不会立即更新服务器状态,而是会等待一段finalizeWait时间(200毫秒)来确定是否有新的更优的投票。原创 2025-04-12 23:51:15 · 1045 阅读 · 0 评论 -
zk源码—6.Leader选举的实现原理一
当Leader故障时,Follower服务器会发生如下操作:首先Follower的followLeader()方法里的while循环会被中断运行,然后在QuorumPeer线程中就会触发执行Follower的shutdown()方法,接着执行QuorumPeer的updateServerState()方法更改节点的状态为LOOKING,之后Follower服务器在QuorumPeer线程中会重新进行Leader选举。zk集群中的服务器分为Leader服务器、Follower服务器及Observer服务器。原创 2025-04-12 23:50:13 · 620 阅读 · 0 评论 -
zk源码—5.请求的处理过程二
Leader中的AckRequestProcessor处理器和Follower中的SendAckRequestProcessor处理器,最终都会触发调用Leader的processAck()方法和tryToCommit()方法,而Leader的tryToCommit()方法又会调用CommitProcessor的commit()方法进行事务提交。对于Learner转发的会话请求,虽然在Learner的会话管理器注册了会话,但还没在Leader的会话管理器中进行注册,因此需要在预处理器进行注册。原创 2025-04-11 09:02:00 · 1114 阅读 · 0 评论 -
zk源码—5.请求的处理过程一
顺序排队的事务请求在被ProposalRequestProcessor处理的过程中,首先会执行CommitProcessor的processRequest()方法将请求加入请求队列,所以请求队列queuedRequests里面的请求是按顺序排好的。除了将请求交给CommitProcessor处理器外,还会创建请求对应的Proposal提议,并将Proposal提议发送给所有Follower来发起一次集群内的事务投票,同时还会将事务请求交给SyncRequestProcessor处理器来记录事务日志。原创 2025-04-11 08:54:26 · 1117 阅读 · 0 评论 -
zk源码—4.会话的实现原理二
当收集完所有需要删除的临时节点,以及创建了对应的节点删除请求后,便会在FinalRequestProcessor的processRequest()方法中,通过调用ZooKeeperServer的processTxn()方法,调用到ZKDatabase的processTxn()方法,最后调用DataTree的killSession()方法,从而最终删除内存数据库中该会话的所有临时节点。zk服务端所有会话过期的相关操作都是围绕过期队列来进行的,可以说zk服务端底层就是通过这个过期队列来管理会话过期的。原创 2025-04-09 23:38:31 · 1284 阅读 · 0 评论 -
zk源码—4.会话的实现原理一
zk客户端在和服务端建立连接时,会提交一个客户端设置的会话超时时间,而该超时时间会和服务端设置的最大超时时间和最小超时时间进行比较。设置会话超时时间后,zk服务端会参考设置的超时时间,最终计算一个服务端自己的超时时间。之后在zk的运行过程中,会在该会话ID的基础上为每个会话分配ID。服务端收到客户端的创建会话请求后,进行会话创建的过程大概分四步:处理ConnectRequest请求、创建会话、请求处理链处理和会话响应。在zk客户端的运行过程(会话生命周期)中,会话会经历不同的状态变化。原创 2025-04-09 23:37:28 · 924 阅读 · 0 评论 -
zk源码—3.单机和集群通信原理二
在Follower的followLeader()方法中,也就是在Learner客户端实例创建完后,会通过findLeader()方法从Leader选举的投票结果中找到Leader服务端,然后通过connectToLeader()方法来建立和该Leader服务端之间的连接。然后调用Leader的getEpochToPropose()方法比较Learner和Leader的epoch,如果Learner的epoch大,则更新Leader的epoch为Learner的epoch + 1。原创 2025-04-08 23:50:23 · 1314 阅读 · 0 评论 -
zk源码—3.单机和集群通信原理一
在执行ZooKeeperServerMain的runFromConfig()方法时,在ZooKeeperServer的startup()方法中调用方法创建并启动好会话管理器后,就会继续在ZooKeeperServer的startup()方法中调用方法初始化请求处理链,也就是在startup()方法中会调用setupRequestProcessors()方法。服务端收到的客户端请求会不断被添加到请求处理器的请求队列中,然后请求处理器线程启动后就会不断从请求队列中提取请求出来进行处理。原创 2025-04-08 23:46:46 · 1105 阅读 · 0 评论 -
zk源码—2.通信协议和客户端原理二
SendThread线程在调用ClientCnxnSocket的doTransport()方法时,会从ClientCnxn的outgoingQueue队列中提取出一个可发送的Packet对象,同时生成一个客户端请求序号XID并将其设置到Packet对象的请求头中,然后再调用Packet对象的createBB方法进行序列化,最后才发送出去。服务端收到Ping包之后,会根据当前时间重置与客户端的Session时间,更新该Session的请求延迟时间,进而保持客户端与服务端的连接状态。原创 2025-04-07 22:53:32 · 719 阅读 · 0 评论 -
zk源码—2.通信协议和客户端原理一
可以看到,ConnectRequest类一共有五种属性字段,分别是:protocolVersion表示该请求协议的版本信息,lastZxidSeen表示最后一次接收到的服务器的zxid序号,timeOut表示会话的超时时间,sessionId表示会话标识符,password表示会话密码。可以看到,SetDataRequest类具有三个属性,分别是:path表示节点的路径,data表示节点数据信息,version表示节点数据的期望版本号,用于乐观锁的验证。这个随机打散的过程是一次性的。原创 2025-04-07 22:52:50 · 872 阅读 · 0 评论 -
zk源码—1.数据节点与Watcher机制及权限二
三.然后将当前的ServerCnxn对象(即Watcher事件)和数据节点路径,传入到zks.getZKDatabase()的getData()方法中来实现Watcher事件的注册,也就是实现存储Watcher事件到WatchManager中。对于标记了Watcher注册的请求,zk会将其对应的ServerCnxn对象(Watcher事件)存储到DataTree里的WatchManager的HashMap(watchTable和watch2Paths)中。这样的设计能够有效减轻服务端的压力。原创 2025-04-06 22:12:12 · 941 阅读 · 0 评论 -
zk源码—1.数据节点与Watcher机制及权限一
如果在这段时间内,zk服务器上该节点的数值恰好被其他客户端更新了,那么该节点的数据版本version值一定也会发生变化,从而导致与客户端携带的version无法匹配,于是无法成功更新。zk的数据模型也具有一个固定的根节点"/",可以在根节点下创建子节点,并在子节点下继续创建下一级节点。比如将集群设置为"/servers"节点,并为集群下的每台服务器创建一个临时节点"/servers/host",当服务器下线时其对应的临时节点就会自动被删除,最后统计临时节点个数就可以知道集群中的运行情况。原创 2025-04-06 22:11:22 · 954 阅读 · 0 评论 -
zk基础—5.Curator的使用与剖析二
每个Curator客户端创建完临时顺序节点后,就会对/leader/latch目录调用getChildren()方法来获取里面所有的子节点,调用getChildren()方法的结果会通过backgroundCallback回调进行通知,接着客户端便对获取到的子节点进行排序来判断自己是否是第一个子节点。当上一个节点对应的客户端释放了Leader角色,上一个节点就会消失,此时就会通知第二个节点对应的客户端,执行getData()方法添加的监听器。每当节点发生变化时,就会触发childEvent()方法的调用。原创 2025-04-05 23:47:43 · 871 阅读 · 0 评论 -
zk基础—5.Curator的使用与剖析一
创建节点也使用了构造器模式:首先通过CuratorFramework的create()方法创建一个CreateBuilder实例,然后通过CreateBuilder的withMode()等方法设置CreateBuilder的变量,最后通过CreateBuilder的forPath()方法 + 重试调用来创建znode节点。首先通过builder()方法创建出Builder实例对象,然后把参数都设置成Builder实例对象的属性,最后通过build()方法把Builder实例对象传入目标类的构造方法中。原创 2025-04-05 23:47:13 · 985 阅读 · 0 评论 -
zk基础—4.zk实现分布式功能二
没有创建临时节点成功的客户端也就没能获得锁,需要到"/exclusive_lock"节点上,注册一个子节点变更的Watcher监听,以便可以实时监听lock节点的变更情况。如果有大量的客户端在等待锁的释放,那么不仅会出现大量的Watcher通知,还会出现大量的获取"/shared_lock"的子节点列表的请求,但最后大部分客户端都会判断出自己并非是序号最小的节点。当控制台进行一些操作时,便会触发修改这些节点的数据,而zk会将这些节点数据的变更以事件通知的形式发送给监听的客户端。原创 2025-04-03 22:52:57 · 1149 阅读 · 0 评论 -
zk基础—4.zk实现分布式功能一
轮询法是最为简单的负载均衡算法。加权轮询法的方式与轮询法的方式很相似,唯一的不同在于选择机器时,不只是单纯按照顺序的方式去选择,还要根据机器的配置和性能高低有所侧重,让配置性能好的机器优先分配。TDDL通过分批获取ID编码的方式,减少了客户端访问服务器的频率,避免了网络波动所造成的影响,并减轻了服务器的内存压力。首先负载均衡服务器在接收到客户端的请求后,通过getData()方法获取已成功注册的业务服务器列表,也就是"/Servers"节点下的各个临时节点,这些临时节点都存储了当前服务器的连接数。原创 2025-04-03 22:51:16 · 905 阅读 · 0 评论 -
zk基础—3.集群与核心参数二
CREATE、READ、WRITE、DELETE、ADMIN,也就是增、删、改、查、管理权限,这5种权限简写为crwda(即:每个单词的首字符缩写)。zk支持某些特定的四字命令字母结合nc与其的交互,这样可以用来获取zk服务的当前状态及相关信息,也就是通过telnet或nc向zk提交相应的命令。创建顺序节点使用-s,可以重复创建"同名"的顺序节点(命令行看起来同名而已,但实际不是同名的)。不管是持久节点还是临时节点,一旦创建完一个节点后,再重复创建同名节点都是不成功的。原创 2025-04-02 22:29:26 · 788 阅读 · 0 评论 -
zk基础—3.集群与核心参数一
zk重启时就可以把包含1000个事务的快照直接加载到内存里,然后把1000之后的32个事务,在内存里回放一遍,即可恢复重启前的数据。一般来说,在启动zk集群之前,首先需要在zoo.cfg配置文件里设置好参数,比如设置zk集群server.1、server.2的信息,设置dataDir、dataLogDir的目录,开启自动清理数据文件等。zk在不停的运行,事务日志会越来越多,但不可能是无限多的,所以zk会切割出多个事务日志文件。即使Follower宕机,也只丢失内存里的数据,磁盘上的事务日志是存在的。原创 2025-04-02 22:27:42 · 851 阅读 · 0 评论 -
zk基础—2.架构原理和使用场景二
同理,如果Leader收到过半Follower的ACK响应后,在发送Commit消息的过程中,出现Leader宕机或者Leader和Follower的网络问题。那么Follower只要与它能找到的Leader(新选举的ZXID最大的Follower或者原来的Leader)进行数据同步,就可以保证新数据在该Follower中完成Commit。某个客户端连接到某个Follower时可以读取到刚刚Commit的数据,但有的客户端连接到另一个Follower时却没法读取到还没有Commit的数据。原创 2025-04-01 21:31:46 · 1089 阅读 · 0 评论 -
zk基础—2.架构原理和使用场景一
集群启动后会自动选举一个Leader出来,只有Leader可以写,Follower只能同步数据和提供数据的读取。zk封装了分布式架构中很多核心和主流的需求功能,比如很多分布式系统都需要分布式锁、集中式存储分布式集群的元数据、Master选举、分布式协调,这些功能需求都可以使用zk来实现。Kafka里使用zk进行元数据管理、Master选举、分布式协调,Canal也一样使用zk进行元数据管理、Master选举(HA主备切换),HDFS的HA也是基于zk来做的。假设现在有3台机器,要进行元数据的存储。原创 2025-04-01 21:31:05 · 655 阅读 · 0 评论 -
zk基础—1.一致性原理和算法二
大纲1.分布式系统特点2.分布式系统的理论3.两阶段提交Two-Phase Commit(2PC)4.三阶段提交Three-Phase Commit(3PC)5.Paxos岛的故事来对应ZooKeeper6.Paxos算法推导过程7.Paxos协议的核心思想8.ZAB算法简述6.Paxos算法推导过程(1)Paxos的概念(2)问题描述(3)推导过程(4)Proposer生成提案(5)Acceptor批准提案(6)Paxos算法描述(7)Learner学习被选定的value(8)如何保证Paxos算法的活性原创 2025-03-31 22:46:13 · 1237 阅读 · 0 评论 -
zk基础—1.一致性原理和算法一
紧接着他又收到了S2的提议,结果他一查记事本,发现这个提议的编号小于等于我的当前编号1,于是拒绝了这个提议:对不起,这个提议先前提过了。因此S2的提议被拒绝,S1的提议被S1和S3同意。每个议员(zk的Server)只会同意大于当前编号(zk的ZXID)的提议(Proposal),包括已生效和未生效的(分布式节点要排除由于网络延迟而晚收到的消息)。Chubby和ZooKeeper都是基于Paxos的理论来实现的,Paxos还被认为是到目前为止唯一的分布式一致性算法,其它的算法都是Paxos的改进或简化。原创 2025-03-31 22:41:50 · 1289 阅读 · 0 评论