一篇文章带你了解 ZooKeeper 架构

上一篇文章,咱们讲解了 ZooKeeper 入门知识,这篇文章主要讲解下 ZooKeeper 的架构,理解 ZooKeeper 的架构能够帮助咱们更好地设计协同服务。java

首先咱们来看下 ZooKeeper 的整体架构图。node

ZooKeeper 整体架构

一篇文章带你了解 ZooKeeper 架构

应用使用 ZooKeeper 客户端库来使用 ZooKeeper 服务,ZooKeeper 客户端会和集群中某一个节点创建 session, ZooKeeper 客户端负责和 ZooKeeper 集群的交互。ZooKeeper 集群能够有两种模式:standalone 模式和 quorum 模式。处于 standalone 模式的 ZooKeeper 集群还有一个独立运行的 ZooKeeper 节点,standalone 模式通常用来开发。实际生产环境 ZooKeeper 通常处于 quorum 模式,在 quorum 模式下 ZooKeeper 集群包换多个 ZooKeeper 节点。数据库

Session

Session 是 ZooKeeper 客户端的一个重要概念,ZooKeeper 客户端库和 ZooKeeper 集群中的节点建立一个 session。客户端能够主动关闭 session。另外若是 ZooKeeper 节点没有在 session 关联的 timeout 时间内收到客户端的数据的话,ZooKeeper 节点也会关闭 session。另外 ZooKeeper 客户端库若是发现链接的 ZooKeeper 出错,会自动的和其余 ZooKeeper 节点创建链接。apache

下图展现了 ZooKeeper 客户端是如何进行重连的?服务器

一篇文章带你了解 ZooKeeper 架构

刚开始 ZooKeeper 客户端和 ZooKeeper 集群中的节点 1 创建的 session,在过了一段时间后,ZooKeeper 节点 1 失败了,ZooKeeper 客户端就自动和 ZooKeeper 集群中的节点 3 从新创建了 session 链接。session

Quorum 模式

处于 Quorum 模式的 ZooKeeper 集群包含多个 ZooKeeper 节点。下图的 ZooKeeper 集群有 3 个节点,其中节点 1 是 leader 节点,节点 2 和节点 3 是 follower 节点。集群中只能有一个 leader 节点,能够有多个 follower 节点,leader 节点能够处理读写请求,follower 只能够处理读请求。follower 在接到写请求时会把写请求转发给 leader 来处理。架构

一篇文章带你了解 ZooKeeper 架构

下面来讲下 ZooKeeper 保证的数据一致性:socket

数据一致性ide

  • •可线性化(Linearizable)写入:先到达 leader 的写请求会被先处理,leader 决定写请求的执行顺序。
  • •客户端 FIFO 顺序:来自给定客户端的请求按照发送顺序执行。

为了让你们更好地理解 Quorum 模式,下面会配置一个 3 节点的 Quorum 模式的 ZooKeeper 集群。.net

搭建 3 节点 ZooKeeper 集群

首先须要准备 3 个配置文件,dataDir 和 clientPort 配置项要配置不一样的值。3 个配置文件的 server.n 部分都是同样的。在 server.1=127.0.0.1:3333:3334,其中 3333 是 quorum 之间的通讯的端口号,3334 是用于 leader 选举的端口号。

还须要在每一个节点的 dataDir 目录下建立 myid 文件,里面内容为一个数字,用来标识当前主机,配置文件中配置的 server.n 中 n 为何数字,则 myid 文件中就输入这个数字。

以下是第 1 个节点的配置文件,其中目录是 node1,端口号用的是 2181,另外两个节点的目录分别是 node2 和 node3,端口号分别为 2182 和 2183,最下面的三行都是同样的:

# 心跳检查的时间 2秒
tickTime=2000
# 初始化时 链接到服务器端的间隔次数,总时间10*2=20秒
initLimit=10
# ZK Leader 和follower 之间通信的次数,总时间5*2=10秒
syncLimit=5
# 存储内存中数据库快照的位置,若是不设置参数,更新事务日志将被存储到默认位置。
dataDir=/data/zk/quorum/node1
# ZK 服务器端的监听端口  
clientPort=2181

server.1=127.0.0.1:3333:3334
server.2=127.0.0.1:4444:4445
server.3=127.0.0.1:5555:5556

下面来启动这个集群,首先启动第一个节点,启动命令以下:

zkServer.sh start-foreground /usr/local/apache-zookeeper-3.5.6-bin/conf/zoo-quorum-node1.cfg

注:start-foreground 选项 zkServer.sh 在前台运行,把日志直接打到 console。若是把日志打到文件的话,这三个 zkServer.sh 会把日志打到同一个文件。

在启动第一个节点后日志中会出现以下:

2019-12-29 13:14:35,758 [myid:1] - WARN  [WorkerSender[myid=1]:QuorumCnxManager@679] - Cannot open channel to 2 at election address /127.0.0.1:4445
java.net.ConnectException: Connection refused (Connection refused)
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:650)
    at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:707)
    at org.apache.zookeeper.server.quorum.QuorumCnxManager.toSend(QuorumCnxManager.java:620)
    at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.process(FastLeaderElection.java:477)
    at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.run(FastLeaderElection.java:456)
    at java.lang.Thread.run(Thread.java:748)

缘由是配置文件中配置的为 3 个节点,可是只启动了 1 个节点,目前他和其余另外两个节点创建不了链接,因此报这个问题。

接下来启动第 2 个节点,执行命令以下:

zkServer.sh start-foreground /usr/local/apache-zookeeper-3.5.6-bin/conf/zoo-quorum-node2.cfg

启动后,咱们能够在节点 2 的日志中发现这么一行:

2019-12-29 13:15:13,699 [myid:2] - INFO  [QuorumPeer[myid=2](plain=/0.0.0.0:2182)(secure=disabled):Leader@464] - LEADING - LEADER ELECTION TOOK - 41 MS

这说明节点 2 成为了 leader 节点,一样能够在节点 1 的日志中发现以下一行日志,说明了节点 1 成为了 follower 节点。

2019-12-29 13:15:13,713 [myid:1] - INFO  [QuorumPeer[myid=1](plain=/0.0.0.0:2181)(secure=disabled):Follower@69] - FOLLOWING - LEADER ELECTION TOOK - 61 MS

由于对于一个三节点集群来讲两个就表明了多数,就造成了 Quorum 模式,接下来启动第 3 个节点,执行命令以下:

zkServer.sh start-foreground /usr/local/apache-zookeeper-3.5.6-bin/conf/zoo-quorum-node3.cfg

启动后在日志中也有以下一行,说明第 3 个节点也加入这个集群,而且是做为 follower 节点加入的。

2019-12-29 13:15:52,440 [myid:3] - INFO  [QuorumPeer[myid=3](plain=/0.0.0.0:2183)(secure=disabled):Follower@69] - FOLLOWING - LEADER ELECTION TOOK - 15 MS

下面来启动客户端来使用这个三节点集群,在命令中加了 -server 选项,后面指定的是三个节点的主机名和端口号,命令以下:

zkCli.sh -server 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
2019-12-29 13:45:44,982 [myid:127.0.0.1:2181] - INFO  [main-SendThread(127.0.0.1:2181):ClientCnxn$SendThread@1394] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x101fff740830000, negotiated timeout = 30000

经过启动日志能够看到客户端和端口号为 2181 的节点创建了链接,也就是和第 1 个节点创建了链接。

咱们执行 ls -R / 命令看下这个集群中的 znode 数据。

[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 1] ls -R /
/
/zookeeper
/zookeeper/config
/zookeeper/quota

下面咱们杀掉一个 ZooKeeper 节点,看客户端是否能进行重连。如今咱们连的节点 1,咱们来把节点 1 杀掉,能够在客户端的日志中发现客户端和端口号为 2183 的节点从新创建了链接,也就是和节点 3 创建了链接。

2019-12-29 14:03:31,392 [myid:127.0.0.1:2183] - INFO  [main-SendThread(127.0.0.1:2183):ClientCnxn$SendThread@1394] - Session establishment complete on server localhost/127.0.0.1:2183, sessionid = 0x101fff740830000, negotiated timeout = 30000

而后咱们再看下客户端可否正常使用,执行 ls -R / ,能够发现可以正常返回数据,说明客户端是可以正常使用的。

[zk: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183(CONNECTED) 4] ls -R /
/
/zookeeper
/zookeeper/config
/zookeeper/quota

总结

这篇文章主要讲解了 ZooKeeper 架构,以及怎样配置一个三节点的 ZooKeeper 集群。

●ZooKeeper 入门看这篇就够了
●Nginx 热部署和日志切割,你学会了吗?
●Nginx 了解一下?
●你真的了解 volatile 关键字吗?
●Java线程的生老病死
●Java 8 Optional:优雅地避免 NPE

一篇文章带你了解 ZooKeeper 架构

武培轩有帮助?在看,转发走一波喜欢做者

相关文章
相关标签/搜索