zookeeper学习

待填坑

目标

  • zk的使用
  • 能基于Maven导入最新版Zookeeper源码
  • 能说出Zookeeper单机启动流程
  • 理解Zookeeper默认通信中4个线程的作用
  • 掌握Zookeeper业务处理源码处理流程
  • 能够在Zookeeper源码中Debug测试通信过程
  • 掌握Zookeeper中Session的管理机制
  • 能基于Client进行Debug测试Session创建/刷新操作
  • 能搭建Zookeeper集群源码配置
  • 掌握集群环境下Leader选举启动过程
  • 能说出Zookeeper选举过程中的概念
  • 能说出Zookeeper选举投票规则
  • 能画出Zookeeper集群数据同步流程

zk的使用

单点和集群部署见kafka篇

生产环境解压即可使用的zk: 见百度网盘

链接:https://pan.baidu.com/s/1ixZEKwtGsHfNSu5Qggw6Mw?pwd=h0h2 
提取码:h0h2 

zkCli的使用

zkCli.sh  -server  master:2181

进入交互界面后,按h 查看帮助
常用 ls /x/xx get /xx/xx stat xx

可视化工具

zooInspector

链接:https://pan.baidu.com/s/1MfWkKq05hR3LTcBdygs5YQ?pwd=pck4 
提取码:pck4 

zk的启动流程

在这里插入图片描述

1.1 启动入口

入口类:QuorumPeerMain,调用initializeAndRun() 方法中会根据配置来决定启动单机Zookeeper还是集群Zookeeper

如果启动单机版,会调用 ZooKeeperServerMain.main(args); ,如果启动
集群版,会调用 QuorumPeerMain.runFromConfig(config);

1.2 单机启动主流程

runFromConfig 方法是单机版启动的主要方法,该方法会做如下几件事:

  1. 初始化各类运行指标,比如一次提交数据最大花费多长时间、批量同步数 据大小等。
  2. 初始化权限操作,例如IP权限、Digest权限。
  3. 创建事务日志操作对象,Zookeeper中每次增加节点、修改数据、删除数 据都是一次事务操作,都会记录日志。
  4. 定义Jvm监控变量和常量,例如警告时间、告警阀值次数、提示阀值次数 等。
  5. 创建ZookeeperServer,这里只是创建,并不在 ZooKeeperServerMain类中启动。
  6. 启动Zookeeper的控制台管理对象AdminServer,该对象采用Jetty启 动。
  7. 创建ServerCnxnFactory,该对象其实是Zookeeper网络通信对象,默 认使用了NIOServerCnxnFactory。
  8. 在ServerCnxnFactory中启动ZookeeperServer服务。
  9. 创建并启动ContainerManager,该对象通过Timer定时执行,清理过期 的容器节点和TTL节点,执行周期为分钟。
  10. 防止主线程结束,阻塞主线程。

1.3 zk网络通信

如何高效的与客户端进行通信,让网络 IO 不成为 ZooKeeper 的瓶颈是ZooKeeper 急需解决的问题, ZooKeeper 中使用 ServerCnxnFactory 管理与客户端的连接,其有两个实现:
一个是 NIOServerCnxnFactory ,使用Java原生 NIO 实现,为默认通信组件;
一个是NettyServerCnxnFactory ,使用netty实现;使用 ServerCnxn 代表一个客户端与服务端的连接。

1.3.1 NIOServerCnxnFactory

NIOServerCnxnFactory 启动时会启动四类线程:

  1. accept thread:该线程接收来自客户端的连接,并将其分配给selector thread(启动一个线程)。
  2. selector thread:该线程执行select(),由于在处理大量连接 时,select()会成为性能瓶颈,因此启动多个selector thread,使用系统属 性zookeeper.nio.numSelectorThreads配置该类线程数,默认个数为 核 心数/2。
  3. worker thread:该线程执行基本的套接字读写,使用系统属性 zookeeper.nio.numWorkerThreads配置该类线程数,默认为核心数∗2核心 数∗2.如果该类线程数为0,则另外启动一线程进行IO处理,见下文worker thread介绍。
  4. connection expiration thread:若连接上的session已过期,则关闭 该连接。

AcceptThread

run 执行 selector.select() ,并调用 doAccept() 接收客户端连接。该方法会轮询获取一个SelectorThread,将当前链接分配给该 SelectorThread

SelectorThread

run方法调select方法从Socket读取数据,并封装成 workRequest ,并将workRequest 交给 workerPool 工作线程池处理

select() 中的核心调用地方是handleIO()

WorkerThread

数据处理将有业务链对象RequestProcessor处理,通过 WorkerService 管理一组 worker thread 线程,前面我们在看 SelectorThread 的时候,能够看到workerPool 的schedule方法被执行,该方法创建了一个新的线程 ScheduledWorkRequest ,并启动了该线程。该线程doWork 方法,在该方法中会调用 doIO 执行IO数据处理

2. session管理机制

在服务端通过 SessionTrackerImpl 和 ExpiryQueue 来保存Session会话
信息。

创建会话调用 createSession(),

session刷新会经过 RequestThrottler的run方法中调用 zks.submitRequestNow() ,而zks.submitRequestNow(request) 中调用了 touch(si.cnxn);

session过期:调用sessionExpiryQueue.poll() ,该方法代码主要是获
取过期时间对应的客户端会话集合,setSessionClosing() 方法其实是把Session会话的 isClosing 状态设置为了true

3. zk集群

3.1 启动流程

启动

  1. loadDataBase()加载数据。
  2. startServerCnxnFactory 用来开启acceptThread、 SelectorThread和workerPool线程池。
  3. 开启Leader选举startLeaderElection。
  4. 开启JVM监控线程startJvmPauseMonitor。
  5. 调用父类super.start();进行Leader选举。

startLeaderElection() 开启Leader选举方法做了2件事,首先创建初始化选票选自己,接着创建选举投票方式,createElectionAlgorithm() 创建选举算法只有第3种创建了以下三个对象:

  • 创建QuorumCnxManager对象
  • QuorumCnxManager.Listener
  • FastLeaderElection

3.2 leader选举

主要依赖于FastLeaderElection算法,是典型的Paxos算法,基于消息传递且具有高度容错特性的一致性算法,三个角色:

  • Proposer
  • Acceptor
  • Learners

负责各台服务器之间的底层Leader选举过程中的网络通信对应的类就是 QuorumCnxManager 。QuorumPeer 主要包括四个组件:客户端请求接收器( ServerCnxnFactory )、数据引擎( ZKDatabase )、选举器( Election )、核心功能组件( Leader/Follower/Observer )。

所有节点初始状态都为LOOKING,会进入到选举流程,选举流程首先要获取算法,获取算法的方法是 makeLEStrategy() ,该方法返回的是FastLeaderElection 实例,核心选举流程是 FastLeaderElection 中的lookForLeader() 方法

过半数以上的方法 hasAllQuorums() 该方法用到了QuorumMaj 类

选票PK的方法 totalOrderPredicate() ,该方法其实就是Leader选举规则,

  1. 比较 epoche(zxid高32bit),如果其他节点的epoche比自己的大,选举 epoch大的节点(理由:epoch 表示年代,epoch越大表示数据越新)代 码:(newEpoch > curEpoch);
  2. 比较 zxid, 如果epoche相同,就比较两个节点的zxid的大小,选举 zxid大的节点(理由:zxid 表示节点所提交事务最大的id,zxid越大代表 该节点的数据越完整)
  3. 比较 serviceId,如果 epoch和zxid都相等,就比较服务的 serverId,选举 serviceId大的节点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值