Zookeeper Server 的启动入口为 org.apache.zookeeper.server.quorum.QuorumPeerMain。Zookeeper 的启动模式分为两种:一种为 standalone mode;另一种为 cluster mode。
- Standalone 模式:当配置文件中仅配置了一台 server 时,Zookeeper 将以 standalone 模式启动,启动类为 ZooKeeperServerMain,此处不作详细分析。
- Cluster 模式:当配置文件中配置了多台 server,构建 cluster,启动类为 QuorumPeer#start()。
1 | public synchronized void start() { |
清理 DataDir
在 Server 启动时,根据启动的配置参数启动一个 TimeTask 用于清理 DataDir 中的 snapshot 及对应的 transactionlog。由于 Zookeeper 的任何一个写操作都将在 transaction log 中留下记录,当写操作达到一定量或者一定时间间隔,Zookeeper 将 transaction log 合并为 snapshot。所以随着运行时间的增长生成的 transaction log 和 snapshot 将越来越多,所以定期清理是必要的。在 DatadirCleanupManager 中有两个参数:
- snapRetainCount:清理后保留的 snapshot 的个数,该参数至少要大于 3。
- purgeInterval:定期清理的时间间隔,以小时为单位。
1 | // Start and schedule the the purge task |
加载 ZKDatabase
1.从 snapshot 和 transaction log 中恢复 ZKDatabase,并将其载入内存。
1 | zkDb.loadDataBase(); |
2.载入 currentEpoch 和 acceptedEpoch
首先要明白什么是 epoch,官方给出的解释是:
The zxid has two parts: the epoch and a counter. In our implementation the zxid is a 64-bit number. We use the high order 32-bits for the epoch and the low order 32-bits for the counter. Because it has two parts represent the zxid both as a number and as a pair of integers, (epoch, count). The epoch number represents a change in leadership. Each time a new leader comes into power it will have its own epoch number.
从 currentEpoch 文件中读取 current epoch;若 currentEpoch 文件不存在,Zookeeper 将从 lastProcessedZxid 中获取 epoch 作为 current epoch,写入 currentEpoch 文件。
1 | try { |
同理,获取 accepted epoch。
1 | try { |
启动 ServerCnxnFactory 线程
ServerCnxnFacotry 是管理 ServerCnxn 处理类的工厂,它负责对 connection 上数据处理的调度,以及 server 级别的一些处理,例如关闭指定 session 等。有关 ServerCnxnFactory 的实现类,可分为三种情况:
- NIO 模式。这是 Zookeeper 默认的 ServerCnxnFactory 实现,其实现类为 NIOServerCnxnFactory。
- Netty 模式。在 Zookeeper 3.4 以后引入了 Netty 作为 Server 端连接处理的可选实现。Netty 是一套非常高效的异步通信框架。可以通过 JVM 参数 zookeeper.serverCnxnFactory 进行配置。
- 自定义模型。Zookeeper 还支持自定类来实现通信,同样可以通过 JVM 参数 zookeeper.serverCnxnFactory 进行配置。
1 | Static public ServerCnxnFactory createFactory() throws IOException { |
ServerCnxnFactory 的主要职责:
- 在单机模式下,引导完成 Zookeeper Server 的实例化。
- 异步接收 Client 的 IO 连接,并维护连接的 IO 操作,这是 ServerCnxnFactory 的核心功能。ServerCnxnFacotry 本身被设计成一个 Thread,在完成初始化工作之后,就开始启动自身线程,在线程 run 方法中,采用 NIO 的方式 Accept 客户端连接,创建一个 NIOServerCnxn 实例,此实例和普通的 NIO 设计思路一样,它持有当前连接的 Channel 句柄和 Buffer 队列,最终将此 NIOServerCnxn 放入 Factory 内部的一个 set 中,以便此后对链接信息进行查询和操作(比如关闭操作,IO 中 read 和 write 操作等)。
Leader 选举
Leader 的选举算法有三种:
- LeaderElection:LeaderElection 采用的是 fast paxos 算法的一种简单实现,目前该算法在 3.4 以后已经建议弃用。
- FastLeaderElection:FastLeaderElection 是标准的 fast paxos 的实现,这是目前 Zookeeper 默认的 Leader 选举算法。
- AuthFastLeaderElection:AuthFastLeaderElection 算法同 FastLeaderElection 算法基本一致,只是在消息中加入了认证信息,该算法在最新的 Zookeeper 中也建议弃用。
Leader 选举算法分析详见:Zookeeper 源码分析-Zookeeper Leader 选举算法
QuorumPeer 启动
完成 DataDir,ZKDatabase 加载以及 Leader 选举动作后,QuorumPeer 完成初始化及启动工作。
参考资料
http://zookeeper.apache.org/doc/r3.4.6/zookeeperInternals.html