zookeeper-入门介绍&架构&使用(这一篇足以)

引言

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务。

具体的安装可以参考我另一篇文章:zookeeper-安装

python操作zk可以参考我的这篇文章:zookeeper-python操作zookeeper

这里对zookeeper做一些整体上的介绍

(顺便推广下我的微信公众号:龙叔18岁)

1·ZK的整体架构

1.1·集群——机器节点

节点角色描述
leader负责系统的写请求,事务请求的唯一调度和处理者,保证集群事务处理的顺序性。集群内部各服务器的调度者。
learnerfollower接受客户端连接,可直接处理读请求,写请求会转发给leader处理;follower还要处理leader的提议,并在leader提交该提议时在本地也进行提交;并参与leader选举
observer

Observer和Follower比较相似,只有一些小区别:首先observer不属于法定人数,即不参加选举也不响应提议;其次是observer不需要将事务持久化到磁盘,一旦observer被重启,需要从leader重新同步整个名字空间。

Observer不参加ZooKeeper的事务提交和选举。
与其他节点的唯一交互是接收来自leader的inform消息,更新自己本地存储。

1.1.1·客户端连接server节点读操作

读请求由客户端所连接到的server直接处理返回,但是因为iserver节点之间数据同步会有网络延迟等问题,不同客户端读到的数据可能不一样

zookeeper保证各节点最终的数据一致,如果需要最新数据,可以在读数据之前调用sync()接口

注解:zookeeper的sync

sync是使得client当前连接着的ZooKeeper服务器,和ZooKeeper的Leader节点同步(sync)一下数据。

当follower收到到sync请求时,会将这个请求添加到一个pendingSyncs队列里,然后将这个请求发送给leader,直到收到leader的Leader.SYNC消息时,才将这个请求从pendingSyncs队列里移除,并commit这个请求。

当Leader收到一个sync请求时,如果leader当前没有待commit的决议,那么leader会立即发送一个Leader.SYNC消息给follower。否则,leader会等到当前最后一个待commit的决议完成后,再发送Leader.SYNC消息给Follower。

如果leader和follower之间的消息通信,是严格按顺序来发送的(TCP保证),因此,当follower接收到Leader.SYNC消息时,说明follower也一定接收到了leader之前(在leader接收到sync请求之前)发送的所有提案或者commit消息。这样,就可以确保follower和leader是同步的了。

1.1.2·客户端连接server节点写操作

节点角色leaderfollowerobserver
写操作流程
  1. leader接收请求
  2. leader发送proposal给follower
  3. follower收到请求记录txlog、snapshot
  4. follower发送ack给leader
  5. leader收到ack后进行commit,并且通知所有的learner,发送commit packet给所有的learner(follower和observer)
  6. leader返回成功给客户端
  1. follower接受请求,解析请求
  2. follower将请求转发给leader
  3. leader接收请求
  4. leader发送proposal给follower
  5. follower收到请求记录txlog、snapshot
  6. follower发送ack给leader
  7. leader收到ack后进行commit,并且通知所有的learner,发送commit packet给所有的learner(follower和observer)
  8. follower返回成功给客户端
  1. observer接受请求,解析请求
  2. observer将请求转发给leader
  3. leader接收请求
  4. leader发送proposal给follower
  5. follower收到请求记录txlog、snapshot
  6. follower发送ack给leader
  7. leader收到ack后进行commit,并且通知所有的learner,发送commit packet给所有的learner(follower和observer)
  8. observer返回成功给客户端
注意点

【1】leader只给follower发送proposal【提议】

【2】半数以上follower返回ack,leader就视为该事务成功,并给其他所有节点发送commit

1.2·ZNode——数据节点

节点类型命令描述
持久节点[zk: localhost:2181(CONNECTED) 25] create  /zkFirst/zk2020/11/08/aa "aa"
Created /zkFirst/zk2020/11/08/aa
创建后永久存在,除非主动删除
临时节点[zk: localhost:2181(CONNECTED) 26] create -e /zkFirst/zk2020/11/08/bb "bb"
Created /zkFirst/zk2020/11/08/bb
临时创建的,会话结束节点自动被删除,也可以手动删除,临时节点不能拥有子节点
顺序节点持久顺序节点[zk: localhost:2181(CONNECTED) 27] create -s /zkFirst/zk2020/11/08/cc "cc"
Created /zkFirst/zk2020/11/08/cc0000000015
Zookeeper将10位的序列号加到原始名称来设置znode的路径给
临时顺序节点[zk: localhost:2181(CONNECTED) 28] create -s -e /zkFirst/zk2020/11/08/dd "dd"
Created /zkFirst/zk2020/11/08/dd0000000016

2·watcher——对ZNode进行监控

ZK允许客户端向服务端注册一个Watcher监听,当服务点的的指定事件触发监听时,那么服务端就会向客户端发送事件通知,以便客户端完成逻辑操作

(即客户端向服务端注册监听,并将watcher对象存在客户端的Watchermanager中,服务端触发事件后,向客户端发送通知,客户端收到通知后从wacherManager中取出对象来执行回调逻辑)

2.1·watcher整体流程图

2.2·可设置watcher的函数

getData、getChildren、exist接口

2.3·可触发watcher的事件

事件说明
NodeCreated (1)Watcher监听的数据节点被创建时
NodeDeleted (2)Watcher监听的数据节点被删除时
NodeDataChanged (3)Watcher监听的数据节点内容发生变更时(无论内容数据是否变化)
NodeChildrenChanged (4)Watcher监听的数据节点的子节点列表发生变更时

2.4·watcher的特性&注意点

1·Watcher是一次性的,一旦被触发就会移除,再次使用时需要重新注册

2·Watcher回调是顺序串行化执行的,只有回调后客户端才能看到最新的数据状态。一个Watcher回调逻辑不应该太多,以免影响别的watcher执行

3·WatchEvent是最小的通信单元,结构上只包含通知状态、事件类型和节点路径,并不会告诉数据节点变化前后的具体内容

4·Watcher只有在当前session彻底失效时才会无效,若在session有效期内快速重连成功,则watcher依然存在,仍可接收到通知

3·ZAB

ZooKeeper Atomic Broadcast (ZAB, ZooKeeper原子消息广播协议)是ZooKeeper实现分布式数据一致性的核心算法,ZAB借鉴Paxos算法,但又不像Paxos算法(一种基于消息传递的一致性算法)那样,是一种通用的分布式一致性算法,它是一种特别为ZooKeeper专门设计的支持崩溃恢复的原子广播协议

根据ZAB协议,所有的写操作都必须通过leader来完成,leader写入本地日志后再复制到所有的follower节点。如果客户端对follower/observer发起写请求,follower/observer会将请求转发到leader,然后由leader处理完成后再将结果转发回follower/observer发送给客户端。

ZAB协议分为消息广播崩溃恢复模式

3.1·协议过程

3.2·消息广播

1. 客户端发起一个写操作请求
2. Leader服务器将客户端的request请求转化为事物proposql提案,同时为每个proposal分配一个全局唯一的ID,即ZXID。
3. leader服务器与每个follower之间都有一个队列,leader将消息发送到该队列
4. follower机器从队列中取出消息处理完(写入本地事物日志中)毕后,向leader服务器发送ACK确认。
5. leader服务器收到半数以上的follower的ACK后,即认为可以发送commit
6. leader向所有的follower服务器发送commit消息。

关键词注解:

1.ZXID:·在消息广播中,leader会将每一个事务请求生成proposal,并在对其进行广播之前给这个事务proposal生成一个全局唯一的递增的 事务id,这个事务id就是ZXID,zookeeper会按照ZXID的先后顺序对事务进行处理,保证了事务的顺序执行。

            ·ZXID是一个64位的数字:

               【低32位】可以看成一个简单的单增计数器,针对客户端每一个事务请求,Leader 在产生新的 Proposal 事务时,都会对该计数器加1。

               【高32位】则代表了 Leader 周期的 epoch 编号。

               (epoch 编号可以理解为当前集群所处的年代,或者周期。每次Leader变更之后都会在 epoch 的基础上加1,这样旧的 Leader 崩溃恢复之后,其他Follower 也不会听它的了,因为 Follower 只服从epoch最高的 Leader 命令)

            ·每当选举产生一个新的 Leader ,就会从这个 Leader 服务器上取出本地事务日志充最大编号 Proposal 的 zxid,并从 zxid 中解析得到对应的 epoch 编号,然后再对其加1,之后该编号就作为新的 epoch 值,并将低32位数字归零,由0开始重新生成zxid。

2.FIFO消息队列:每个follower都有一个FIFO的消息队列,用于leader和follower之间收发消息,使用队列,leader与follower只需要往队列中发送消息即可,实现异步,避免了同步可能造成的阻塞,队列是FIFO的,保证了事务的顺序执行。

3.3·崩溃恢复

在集群启动和集群运行期间leader异常的时候,会进入崩溃恢复模式进行leader的选举


3.3.1·相关名词解释

这些关键词在日志中也可以看到,

·WorkerReceiver:接收投票信息工作线程

·WorkerSender:发送投票信息的工作线程

·QuorumPeer:这个类就是zookeeper的Leader选举的启动类,负责创建选举算法,zk数据恢复,启动leader选举等

·QuorumCnxManager(qcm): 实现领导选举中的网络连接管理功能。它为每一对节点维护唯一的一个连接,在两个节点都启动申请连接时,只有sid大的一方才会申请连接成功。qcm对每个节点维护一个消息发送队列。

·NIOServerCnxn:处理与客户端之间的通信,使用单线程处理

·LearnerHandler

      为了保证整个集群内部的实时通信,同时为了确保可以控制所有的Follower/Observer服务器,Leader服务器会与每个Follower/Observer服务器建立一个TCP长连接。同时也会为每个Follower/Observer服务器创建一个名为LearnerHandler的实体。

      LearnerHandler是Learner服务器的管理者,主要负责Follower/Observer服务器和Leader服务器之间的一系列网络通信,包括数据同步、请求转发和Proposal提议的投票等。

      Leader服务器中保存了所有Follower/Observer对应的LearnerHandler。

      Leader和每个Learner连接会维持一个长连接,并有一个单独的LearnerHandler线程和一个Learner进行交互

·peerEpoch:每次leader选举完成之后,都会选举出一个新的peerEpoch,用来标记事务请求所属的轮次

·electionEpoch:每执行一次leader选举,electionEpoch就会自增,用来标记leader选举的轮次

·peerLastZxid:Learner服务器(Follower或observer)最后处理的zxid。

·lastProcessedZxid:最后一次commit的事务请求的zxid(leader服务器最大的ZXID)

·minCommittedLog:Leader服务器proposal缓存队列committedLog中的最小的zxid。

·maxCommittedLog:Leader服务器proposal缓存队列committedLog中的最大的zxid。

3.3.2·成为leader的条件

1)选 epoch 最大的
2)若 epoch 相等,选 zxid 最大的
3)若 epoch 和 zxid 相等,选择 server_id 最大的(zoo.cfg中的myid)

Zab协议需要保证选举出来的Leader需要满足以下条件:
1)新选举出来的 Leader 不能包含未提交的 Proposal
即新选举的 Leader 必须都是已经提交了 Proposal 的 Follower 服务器节点。
2)新选举的 Leader 节点中含有最大的 zxid
这样做的好处是可以避免 Leader 服务器检查 Proposal 的提交和丢弃工作。

3.3.3·选举过程中节点的服务器状态

在leader选举过程中,服务器有下面四种状态:

·LOOKING:寻找leader状态,只要当前服务器状态为LOOKING,进入循环,不断地读取其它Server发来的通知、进行比较、更新自己的投票、发送自己的投票、统计投票结果,直到leader选出或出错退出。

·LEADING:领导状态(节点为leader)

·FOLLOWING:跟随者状态

·OBSERVING:观察者状态(此状态不参与选举)

3.3.4·集群启动时的选举过程

因为选举需要至少两台机器,所以当启动两个服务器的时候,选举就开始了,换句话说,集群启动的时候,leader会在最开始启动的两个服务器中选举出来

这里以server-1(myid=1),server-2(myid=2),server-3(myid=3),三个服务器节点的集群为例:

【1】选举示意图

【2】集群启动的日志解读

【第一步】先启动server-1

日志报错连接不上另外两个节点,目前集群是不可用的,SERVER-1一开始进入LOOKING状态

【第二步】再启动server-2

目前有了两个节点,则开始leader选举,因为ZXID相同,所以选举了myid较大的server-2

——新起的server-2节点日志:

【leader选举】
2020-11-17 23:36:44,418 [myid:2] - INFO  [main:QuorumCnxManager$Listener@878] - Election port bind maximum retries is 3
2020-11-17 23:36:44,429 [myid:2] - INFO  [QuorumPeerListener:QuorumCnxManager$Listener@929] - 2 is accepting connections now, my election bind port: /0.0.0.0:3888【选举监听端口】
2020-11-17 23:36:44,437 [myid:2] - INFO  [QuorumPeer[myid=2](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):QuorumPeer@1175] - LOOKING【进入leader选举状态,只要当前服务器状态为LOOKING,进入循环,不断地读取其它Server发来的通知、进行比较、更新自己的投票、发送自己的投票、统计投票结果,直到leader选出或出错退出。】
2020-11-17 23:36:44,438 [myid:2] - INFO  [QuorumPeer[myid=2](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):FastLeaderElection@903] - New election. My id =  2, proposed zxid=0x600
000067
2020-11-17 23:36:44,450 [myid:2] - INFO  [WorkerReceiver[myid=2]:FastLeaderElection@697] - Notification: 2 (message format version), 2 (n.leader), 0x600000067 (n.zxid), 0x1 (n.round), LOOKING (n.state), 2 (n.sid), 0x6 (n.peerEPoch), LOOKING (my state)0 (n.config version)【WorkerReceiver是接收投票信息工作线程】
2020-11-17 23:36:44,458 [myid:2] - WARN  [QuorumConnectionThread-[myid=2]-2:QuorumCnxManager@381] - Cannot open channel to 3 at election address /192.168.30.128:3888【这个时候因为server-3没有启动,所以还在报连不上节点3】
java.net.ConnectException: 拒绝连接 (Connection refused)
        at java.net.PlainSocketImpl.socketConnect(Native Method)
        。。。【此处省略报错】

2020-11-17 23:36:44,464 [myid:2] - INFO  [WorkerReceiver[myid=2]:FastLeaderElection@697] - Notification: 2 (message format version), 1 (n.leader), 0x600000067 (n.zxid), 0x1 (n.round), LOOKING (n.state), 1 (n.sid), 0x6 (n.peerEPoch), LOOKING (my state)0 (n.config version)
2020-11-17 23:36:44,464 [myid:2] - INFO  [WorkerReceiver[myid=2]:FastLeaderElection@697] - Notification: 2 (message format version), 2 (n.leader), 0x600000067 (n.zxid), 0x1 (n.round), LOOKING (n.state), 1 (n.sid), 0x6 (n.peerEPoch), LOOKING (my state)0 (n.config version)
2020-11-17 23:36:44,667 [myid:2] - INFO  [QuorumPeer[myid=2](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):QuorumPeer@1263] - LEADING【leader选举结束,进入leader状态】
。。。【省略一些信息类日志】
2020-11-17 23:37:07,201 [myid:2] - INFO  [QuorumPeer[myid=2](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):Leader@464] - LEADING - LEADER ELECTION TOOK - 22535 MS【选举结束:server-2被选举成为leader节点】
2020-11-17 23:37:07,211 [myid:2] - INFO  [QuorumPeer[myid=2](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):FileTxnSnapLog@404] - Snapshotting: 0x600000067 to /usr/local/zookeeper/data/version-2/snapshot.600000067
2020-11-17 23:37:07,246 [myid:2] - INFO  [LearnerHandler-/192.168.30.133:34174:LearnerHandler@406] - Follower sid: 1 : info : 192.168.30.133:2888:3888:participant【leader与server-1这个follower节点维持一个长连接】
2020-11-17 23:37:07,262 [myid:2] - INFO  [LearnerHandler-/192.168.30.133:34174:ZKDatabase@295] - On disk txn sync enabled with snapshotSizeFactor 0.33

【选举完成之后的数据同步】
2020-11-17 23:37:07,262 [myid:2] - INFO  [LearnerHandler-/192.168.30.133:34174:LearnerHandler@708] - Synchronizing with Follower sid: 1 maxCommittedLog=0x600000067 minCommittedLog=0x600000001 lastProcessedZxid=0x600000067 peerLastZxid=0x600000067【follower-1 最后处理的ZXID是0x600000067(peerLastZxid),Leader服务器(server-2)提交在队列中的最小zxid为0x600000001 (minCommittedLog),最大zxid为0x600000067 (maxCommittedLog),因为minCommittedLog<=peerLastZxid<=maxCommittedLog,所以选用同步方式位diff】
2020-11-17 23:37:07,263 [myid:2] - INFO  [LearnerHandler-/192.168.30.133:34174:LearnerHandler@752] - Sending DIFF zxid=0x600000067 for peer sid: 1【向server-1发起diff数据同步】
2020-11-17 23:37:07,293 [myid:2] - INFO  [QuorumPeer[myid=2](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):Leader@1296] - Have quorum of supporters, sids: [ [1, 2],[1, 2] ]; starting up and setting last processed zxid: 0x700000000
2020-11-17 23:37:07,313 [myid:2] - INFO  [QuorumPeer[myid=2](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):CommitProcessor@256] - Configuring CommitProcessor with 1 worker threads.
2020-11-17 23:37:07,320 [myid:2] - INFO  [QuorumPeer[myid=2](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):ContainerManager@64] - Using checkIntervalMs=60000 maxPerMinute=10000
2020-11-17 23:37:37,587 [myid:2] - INFO  [SessionTracker:ZooKeeperServer@398] - Expiring session 0x3000001567a0001, timeout of 30000ms exceeded
2020-11-17 23:37:37,588 [myid:2] - INFO  [SessionTracker:QuorumZooKeeperServer@157] - Submitting global closeSession request for session 0x3000001567a0001
2020-11-17 23:37:37,590 [myid:2] - INFO  [SyncThread:2:FileTxnLog@218] - Creating new log file: log.700000001

——server-1节点日志:

【leader选举】

2020-11-17 23:36:44,455 [myid:1] - INFO  [/0.0.0.0:3888:QuorumCnxManager$Listener@936] - Received connection request from /192.168.30.135:49736这里接收到了server-2的连接】
2020-11-17 23:36:44,463 [myid:1] - INFO  [WorkerReceiver[myid=1]:FastLeaderElection@697] - Notification: 2 (message format version), 2 (n.leader), 0x600000067 (n.zxid), 0x1 (n.round), LOOKING (n.state), 2 (n.sid), 0x6 (n.peerEPoch), LOOKING (my state)0 (n.config version)【WorkerReceiver是接收投票信息工作线程】
2020-11-17 23:36:44,465 [myid:1] - INFO  [WorkerReceiver[myid=1]:FastLeaderElection@697] - Notification: 2 (message format version), 2 (n.leader), 0x600000067 (n.zxid), 0x1 (n.round), LOOKING (n.state), 1 (n.sid), 0x6 (n.peerEPoch), LOOKING (my state)0 (n.config version)
2020-11-17 23:36:44,466 [myid:1] - WARN  [QuorumConnectionThread-[myid=1]-5:QuorumCnxManager@381] - Cannot open channel to 3 at election address /192.168.30.128:3888【这个时候因为server-3没有启动,所以还在报连不上节点3】
java.net.ConnectException: 拒绝连接 (Connection refused)
        at java.net.PlainSocketImpl.socketConnect(Native Method)
        。。。【此处省略报错】
2020-11-17 23:36:44,667 [myid:1] - INFO  [QuorumPeer[myid=1](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):QuorumPeer@1251] - FOLLOWING【leader选举结束,进入follower状态】
2020-11-17 23:36:44,677 [myid:1] - INFO  [QuorumPeer[myid=1](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):Learner@91] - TCP NoDelay set to: true【这个类就是zookeeper的Leader选举的启动类,负责创建选举算法,zk数据恢复,启动leader选举等】
2020-11-17 23:36:52,893 [myid:1] - INFO  [NIOWorkerThread-2:NIOServerCnxn@518] - Processing srvr command from /127.0.0.1:39132NIOServerCnxn处理与客户端之间的通信,使用单线程处理】
。。。【省略一些信息类日志】
2020-11-17 23:37:07,193 [myid:1] - INFO  [QuorumPeer[myid=1](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):Follower@69] - FOLLOWING - LEADER ELECTION TOOK - 22526 MS【选举结束:server-1被选举成为follower节点】

【选举完成之后的数据同步】
2020-11-17 23:37:07,276 [myid:1] - INFO  [QuorumPeer[myid=1](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):Learner@391] - Getting a diff from the leader 0x600000067【接收到leader的diff同步请求】
2020-11-17 23:37:07,286 [myid:1] - INFO  [QuorumPeer[myid=1](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):Learner@546] - Learner received NEWLEADER message
2020-11-17 23:37:07,324 [myid:1] - INFO  [QuorumPeer[myid=1](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):Learner@529] - Learner received UPTODATE message
2020-11-17 23:37:07,327 [myid:1] - INFO  [QuorumPeer[myid=1](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):CommitProcessor@256] - Configuring CommitProcessor with 1 worker threads.
2020-11-17 23:37:37,598 [myid:1] - WARN  [QuorumPeer[myid=1](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):Follower@125] - Got zxid 0x700000001 expected 0x1
2020-11-17 23:37:37,599 [myid:1] - INFO  [SyncThread:1:FileTxnLog@218] - Creating new log file: log.700000001
 

【第三步】再启动server-3

因为集群已经有了leader,所以server-3作为了follower加入了集群

server-2节点(leader)的日志:

2020-11-17 23:38:17,051 [myid:2] - INFO  [/0.0.0.0:3888:QuorumCnxManager$Listener@936] - Received connection request from /192.168.30.128:47270
2020-11-17 23:38:17,069 [myid:2] - INFO  [WorkerReceiver[myid=2]:FastLeaderElection@697] - Notification: 2 (message format version), 3 (n.leader), 0x600000067 (n.zxid), 0x1 (n.round), LOOKING (n.state), 3 (n.sid), 0x6 (n.peerEPoch), LEADING (my state)0 (n.config version)
2020-11-17 23:38:17,108 [myid:2] - INFO  [LearnerHandler-/192.168.30.128:33790:LearnerHandler@406] - Follower sid: 3 : info : 192.168.30.128:2888:3888:participant
2020-11-17 23:38:17,111 [myid:2] - INFO  [LearnerHandler-/192.168.30.128:33790:ZKDatabase@295] - On disk txn sync enabled with snapshotSizeFactor 0.33
2020-11-17 23:38:17,111 [myid:2] - INFO  [LearnerHandler-/192.168.30.128:33790:LearnerHandler@708] - Synchronizing with Follower sid: 3 maxCommittedLog=0x700000001 minCommittedLog=0x600000001 lastProcessedZxid=0x700000001 peerLastZxid=0x600000067
2020-11-17 23:38:17,111 [myid:2] - INFO  [LearnerHandler-/192.168.30.128:33790:LearnerHandler@769] - Using committedLog for peer sid: 3
2020-11-17 23:38:17,111 [myid:2] - INFO  [LearnerHandler-/192.168.30.128:33790:LearnerHandler@859] - Sending DIFF zxid=0x700000001 for peer sid: 3
2020-11-17 23:39:36,552 [myid:2] - INFO  [NIOWorkerThread-1:FourLetterCommands@234] - The list of known four letter word commands is : [{1936881266=srvr, 1937006964=stat, 2003003491=wchc, 1685417328=dump, 1668445044=crst, 1936880500=srst, 1701738089=envi, 1668247142=conf, -720899=telnet close, 2003003507=wchs, 2003003504=wchp, 1684632179=dirs, 1668247155=cons, 1835955314=mntr, 1769173615=isro, 1920298859=ruok, 1735683435=gtmk, 1937010027=stmk}]
2020-11-17 23:39:36,552 [myid:2] - INFO  [NIOWorkerThread-1:FourLetterCommands@235] - The list of enabled four letter word commands is : [[srvr]]
2020-11-17 23:39:36,552 [myid:2] - INFO  [NIOWorkerThread-1:NIOServerCnxn@518] - Processing srvr command from /127.0.0.1:35350

server-3节点(新follower)的日志:

2020-11-17 23:38:16,954 [myid:3] - INFO  [QuorumPeerListener:QuorumCnxManager$Listener@929] - 3 is accepting connections now, my election bind port: /0.0.0.0:3888
2020-11-17 23:38:16,983 [myid:3] - INFO  [QuorumPeer[myid=3](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):QuorumPeer@1175] - LOOKING【寻找leader】
2020-11-17 23:38:16,988 [myid:3] - INFO  [QuorumPeer[myid=3](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):FastLeaderElection@903] - New election. My id =  3, proposed zxid=0x600000067
2020-11-17 23:38:16,996 [myid:3] - INFO  [WorkerReceiver[myid=3]:FastLeaderElection@697] - Notification: 2 (message format version), 3 (n.leader), 0x600000067 (n.zxid), 0x1 (n.round), LOOKING (n.state), 3 (n.sid), 0x6 (n.peerEPoch), LOOKING (my state)0 (n.config version)
2020-11-17 23:38:17,012 [myid:3] - INFO  [WorkerReceiver[myid=3]:FastLeaderElection@697] - Notification: 2 (message format version), 2 (n.leader), 0x600000067 (n.zxid), 0x1 (n.round), LOOKING (n.state), 1 (n.sid), 0x6 (n.peerEPoch), LOOKING (my state)0 (n.config version)
2020-11-17 23:38:17,034 [myid:3] - INFO  [WorkerReceiver[myid=3]:FastLeaderElection@697] - Notification: 2 (message format version), 2 (n.leader), 0x600000067 (n.zxid), 0x1 (n.round), FOLLOWING (n.state), 1 (n.sid), 0x7 (n.peerEPoch), LOOKING (my state)0 (n.config version)
2020-11-17 23:38:17,035 [myid:3] - INFO  [WorkerReceiver[myid=3]:FastLeaderElection@697] - Notification: 2 (message format version), 2 (n.leader), 0x600000067 (n.zxid), 0x1 (n.round), LOOKING (n.state), 2 (n.sid), 0x6 (n.peerEPoch), LOOKING (my state)0 (n.config version)
2020-11-17 23:38:17,035 [myid:3] - INFO  [WorkerReceiver[myid=3]:FastLeaderElection@697] - Notification: 2 (message format version), 2 (n.leader), 0x600000067 (n.zxid), 0x1 (n.round), LEADING (n.state), 2 (n.sid), 0x7 (n.peerEPoch), LOOKING (my state)0 (n.config version)
2020-11-17 23:38:17,037 [myid:3] - INFO  [QuorumPeer[myid=3](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):QuorumPeer@1251] - FOLLOWING
。。。【省略一些信息类日志】
2020-11-17 23:38:17,056 [myid:3] - INFO  [QuorumPeer[myid=3](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):Follower@69] - FOLLOWING - LEADER ELECTION TOOK - 19 MS【发现集群已有leader,自身成为follower】
2020-11-17 23:38:17,069 [myid:3] - INFO  [QuorumPeer[myid=3](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):Learner@391] - Getting a diff from the leader 0x700000001
2020-11-17 23:38:17,072 [myid:3] - WARN  [QuorumPeer[myid=3](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):Learner@454] - Got zxid 0x700000001 expected 0x1
2020-11-17 23:38:17,073 [myid:3] - INFO  [QuorumPeer[myid=3](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):Learner@546] - Learner received NEWLEADER message
2020-11-17 23:38:17,078 [myid:3] - INFO  [QuorumPeer[myid=3](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):Learner@529] - Learner received UPTODATE message
2020-11-17 23:38:17,083 [myid:3] - INFO  [QuorumPeer[myid=3](plain=[0:0:0:0:0:0:0:0]:2181)(secure=disabled):CommitProcessor@256] - Configuring CommitProcessor with 1 worker threads.
2020-11-17 23:38:17,113 [myid:3] - INFO  [SyncThread:3:FileTxnLog@218] - Creating new log file: log.700000001
2020-11-17 23:39:43,869 [myid:3] - INFO  [NIOWorkerThread-1:FourLetterCommands@234] - The list of known four letter word commands is : [{1936881266=srvr, 1937006964=stat, 2003003491=wchc, 1685417328=dump, 1668445044=crst, 1936880500=srst, 1701738089=envi, 1668247142=conf, -720899=telnet close, 2003003507=wchs, 2003003504=wchp, 1684632179=dirs, 1668247155=cons, 1835955314=mntr, 1769173615=isro, 1920298859=ruok, 1735683435=gtmk, 1937010027=stmk}]
2020-11-17 23:39:43,870 [myid:3] - INFO  [NIOWorkerThread-1:FourLetterCommands@235] - The list of enabled four letter word commands is : [[srvr]]
2020-11-17 23:39:43,870 [myid:3] - INFO  [NIOWorkerThread-1:NIOServerCnxn@518] - Processing srvr command from /127.0.0.1:33432
 

3.3.5·集群运行期间的选举过程

集群运行期间因为leader节点崩溃会导致leader的选举,整体和集群启动时的leader选举差不多,示意图如下

3.3.6·leader选举之后的数据同步

数据同步方式有四种,决定用哪一种,是根据下面的四个参数

·peerLastZxid:Learner服务器(Follower或observer)最后处理的zxid。

·lastProcessedZxid:最后一次commit的事务请求的zxid(leader服务器最大的ZXID)

·minCommittedLog:Leader服务器proposal缓存队列committedLog中的最小的zxid。

·maxCommittedLog:Leader服务器proposal缓存队列committedLog中的最大的zxid。

【1】同步方式1:DIFF(直接差异化同步)

当Follower最大的zxid小于maxCommittedZxid且大于minCommittedZxid

【2】同步方式2:TRUNC+DIFF(先回滚再差异化同步)

当新的 Leader 服务器发现某个 Learner 服务器包含了一条自己没有的事务记录,那么就需要让该 Learner 服务器进行事务回滚--回滚到 Leader服务器上存在的,同时也是最接近于 peerLastZxid 的 ZXID

【3】同步方式3:TRUNC(仅回滚同步)

当Follower最大的zxid大于maxCommittedZxid时,该方式要求Follower丢弃超出的那部分Proposal

【4】同步方式4:SNAP(全量同步)

当Follower最大的zxid小于minCommittedZxid时,该方式直接同步快照给Follower

或者

Leader 服务器上没有 Proposal 缓存队列且 peerLastZxid 不等 于 lastProcessZxid

5·zookeeper开源辅助工具

zkweb,zkui,Shepher 等等网上可以找到不少开源的zookeeper管理工具,可以根据需要搜索看看

推荐公众号,分享运维知识:龙叔18岁

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙叔运维

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值