一篇文章带你了解 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 客户端是如何进行重连的?segmentfault

ZooKeeper重连

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

Quorum 模式

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

Quorum模式

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

数据一致性socket

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

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

搭建 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 集群。

相关文章
相关标签/搜索