4. ZooKeeper

2 ZooKeeper

2.1 ZooKeeper使用场景

ZooKeeper是一个分布式服务框架, 它主要是用来解决分布式应用中经常遇到的一些数据管理问题, 如: 命名服务, 状态同步, 配置中心, 集群管理等

  • 命名服务: 命令服务是分布式系统中比较常见的一类场景. 命名服务是分布式系统最基本的公共服务之一. 在分布式系统中, 被命名的实体通常可以是集群中的机器, 提供的服务地址或远程对象等. 这些我们都可以统称为名字, 其中较为常见的就是一些分布式服务框架(如 RPC, RMI)中的服务地址列表, 通过使用命名服务, 客户端应用能够根据指定名字来获取资源的实体, 服务地址和提供者的信息等.
image.png
  • 状态同步: 解决微服务场景下, 服务动态扩容或者缩容时, 服务动态发现的问题. 不同的服务会将自己注册到ZooKeeper, 消费者通过连接ZooKeeper去获得服务的地址. 无论是微服务扩容还是服务宕机, ZooKeeper都会同步给消费者, 保证消费者连接的都是可用的最新的服务地址

    每个节点除了存储数据内容和node节点状态信息之外, 还存储了已经注册的APP状态信息, 当有些节点或APP不可用, 就将当前状态同步给其他服务.

  • 配置中心: 现在我们大多数应用都是采用的是分布式开发的应用, 搭建到不同的服务器上, 对于配置文件, 同一个应用程序的配置文件一样, 还有就是多个程序存在相同的配置, 当我们配置文件中有个配置属性需要改变, 我们需要改变每个程序的配置属性, 这样会很麻烦的去修改配置, 那么可以使用ZooKeeper来实现配置中心. ZooKeeper采用的是推拉相结合的方式: 客户端向服务端注册自己需要关注的节点, 一旦该节点的数据发生变更, 那么服务端就会向相应的客户端发送Watcher事件通知, 客户端接收到这个消息通知后, 需要主动到服务端获取最新的数据

  • 集群管理: 所谓的集群管理, 包括集群监控与集群控制两大块, 前者侧重对集群运行时状态的收集, 后者则是对集群进行操作和控制, 在日常开发和运维过程中, 我们经常会有类似于如下的需求:

希望知道当前集群中究竟有多少机器在工作
对集群中每台机器的运行时状态进行数据收集
对集群中机器进行上下线操作

ZooKeeper具有以下两大特性

  • 客户端如果对ZooKeeper的一个数据节点注册Watcher监听, 那么当该数据节点的内容或是其子节点列表发生变更时, ZooKeeper服务器就会向订阅的客户端发送变更通知. 对在ZooKeeper上创建的临时节点, 一旦客户端与服务器之间的会话失效, 那么该临时节点也就会被自动清除
  • Watcher(事件监听器), 是ZooKeeper中的一个很重要的特性. ZooKeeper允许用户在指定节点上注册一些Watcher,. 并且在一些特定事件触发的时候, ZooKeeper服务端会将事件通知到感兴趣的客户端上去, 该机制是ZooKeeper实现分布式协调服务的重要特性
image.png
0 生产者启动
1 生产者注册至ZooKeeper
2 消费者启动并订阅频道
3 ZooKeeper通知消费者事件
4 消费者调用生产者
5 监控中心负责统计和监控服务状态

2.2 ZooKeeper单机安装

单机版的ZooKeeper安装

10.0.0.209

2.2.1 配置Java环境

官方依赖介绍: https://zookeeper.apache.org/doc/r3.4.14/zookeeperAdmin.html#sc_requiredSoftware

root@zookeeper:~# apt install openjdk-8-jdk -y

2.2.2 部署ZooKeeper-3.5.8

下载二进制包: https://archive.apache.org/dist/zookeeper/zookeeper-3.5.8/

root@zookeeper:~# mkdir /apps
root@zookeeper:~# cd /apps
root@zookeeper:/apps# rz -E
rz waiting to receive.
root@zookeeper:/apps# ls
apache-zookeeper-3.5.8-bin.tar.gz
root@zookeeper:/apps# tar xvf apache-zookeeper-3.5.8-bin.tar.gz
root@zookeeper:/apps# cd apache-zookeeper-3.5.8-bin/bin
root@zookeeper:/apps/apache-zookeeper-3.5.8-bin/bin# ll
total 64
drwxr-xr-x 2 root root 4096 May  4  2020 ./
drwxr-xr-x 6 root root 4096 Dec 15 15:54 ../
-rwxr-xr-x 1 root root  232 May  4  2020 README.txt*
-rwxr-xr-x 1 root root 2067 May  4  2020 zkCleanup.sh*
-rwxr-xr-x 1 root root 1158 May  4  2020 zkCli.cmd*
-rwxr-xr-x 1 root root 1621 May  4  2020 zkCli.sh* #Linux客户端脚本, 可以连接到ZooKeeper服务器执行操作
-rwxr-xr-x 1 root root 1766 May  4  2020 zkEnv.cmd*
-rwxr-xr-x 1 root root 3690 May  4  2020 zkEnv.sh*
-rwxr-xr-x 1 root root 1286 May  4  2020 zkServer.cmd*
-rwxr-xr-x 1 root root 4573 May  4  2020 zkServer-initialize.sh*
-rwxr-xr-x 1 root root 9386 May  4  2020 zkServer.sh* #Linux服务启动脚本
-rwxr-xr-x 1 root root  996 May  4  2020 zkTxnLogToolkit.cmd*
-rwxr-xr-x 1 root root 1385 May  4  2020 zkTxnLogToolkit.sh*

2.2.3 编辑配置文件

root@zookeeper:/apps/apache-zookeeper-3.5.8-bin/conf# ll
total 20
drwxr-xr-x 2 root root 4096 May  4  2020 ./
drwxr-xr-x 6 root root 4096 Dec 15 15:54 ../
-rw-r--r-- 1 root root  535 May  4  2020 configuration.xsl
-rw-r--r-- 1 root root 2712 May  4  2020 log4j.properties
-rw-r--r-- 1 root root  922 May  4  2020 zoo_sample.cfg  #模板配置文件
root@zookeeper:/apps/apache-zookeeper-3.5.8-bin/conf# cp zoo_sample.cfg zoo.cfg
root@zookeeper:/apps/apache-zookeeper-3.5.8-bin/conf# vim zoo.cfg
# The number of milliseconds of each tick                                                                                                           
tickTime=2000 #集群中, 定义每次选举的时间
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10 #集群中, 定义初始化次数的超时时间
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5 #集群中, 数据同步成功的超时次数
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
# dataDir=/tmp/zookeeper #ZooKeeper数据目录的保存位置
dataDir=/apps/apache-zookeeper-3.5.8-bin/data                                                                                                       
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1

2.2.4 启动ZooKeeper

root@zookeeper:/apps/apache-zookeeper-3.5.8-bin/bin# ./zkServer.sh start
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /apps/apache-zookeeper-3.5.8-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED

2.2.5 验证ZooKeeper进程

root@zookeeper:/apps/apache-zookeeper-3.5.8-bin/bin# ./zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /apps/apache-zookeeper-3.5.8-bin/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: standalone #单机模式
root@zookeeper:/apps/apache-zookeeper-3.5.8-bin/bin# ss -ntl
State             Recv-Q              Send-Q                            Local Address:Port                            Peer Address:Port             
LISTEN            0                   128                               127.0.0.53%lo:53                                   0.0.0.0:*                
LISTEN            0                   128                                     0.0.0.0:22                                   0.0.0.0:*                
LISTEN            0                   50                                            *:8080                                       *:*                
LISTEN            0                   128                                        [::]:22                                      [::]:*                
LISTEN            0                   50                                            *:46813                                      *:*                
LISTEN            0                   50                                            *:2181    #ZooKeeper监听2181端口                                   *:* 

2.2.6 测试数据写入

#!/usr/bin/env python

def myzk():
    from kazoo.client import KazooClient
    zk = KazooClient(hosts='10.0.0.209:2181')
    zk.start()
    zk.create('/zoo/data',makepath=True) #makepath=True 递归创建目录
    ret=zk.set('/zoo/data',"Hello World")
    data=zk.get("/zoo/data")
    print(data)
    zk.stop()
myzk()

2.2.7 利用客户端脚本, 操作ZooKeeper

root@zookeeper:/apps/apache-zookeeper-3.5.8-bin/bin# ./zkCli.sh
...
[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper] #zookeeper相当于/下的一个目录
[zk: localhost:2181(CONNECTED) 1] ls /zookeeper
[config, quota] #config, quota相当于zookeeper目录里的key
[zk: localhost:2181(CONNECTED) 6] get /zookeeper/quota #get命令查看一个key的值, 这里quota默认没有value

还原虚拟机准备集群搭建

2.3 ZooKeeper集群

图片.png

图片.png

图片.png
图片.png

ZooKeeper集群用于解决单点和单机性能及数据高可用等问题

ZooKeeper是复制集群, 数据在每个节点都是相同的

通过选举, 选出一个唯一的leader, 数据的写入只通过leader写入, 因为如果通过其他节点写入, 无法保证数据一致性

客户端连接到follower后写入数据, follower会把数据路由给leader, 由leader完成数据写入, leader完成写入后, 会把数据同步到其他follower节点. 消费者可以连接到任意节点去消费数据. 如果leader宕机, 剩余节点会再次选举出一个leader

ZooKeeper特性1:

写操作的"过半写成功策略": 用来判断数据何时被认为写入完毕

举例. 当有五个节点, 其中一个Leader节点, 四个Follower节点时

客户端发起数据写入操作, 会由连接的follower把数据路由给leader, 由leader完成数据写入, 再由leader同步给其他的follower节点. 过半写成功策略就规定了, 集群中, 有半数以上完成了数据写入, 就认为数据写入完毕, 返回给客户端数据写入完毕, 之后再由leader把数据同步到其余未完成数据写入的节点, 有助于写入性能提供

2.4 集群部署

zookeeper 集群特性:整个集群中只要有超过集群数量一半的 zookeeper 工作是正常的,那么整个集群对外就是可用的,假如有 2 台服务器做了一个 zookeeper集群,只要有任何一台故障或宕机,那么这个zookeeper 集群就不可用了,因为剩下的一台没有超过集群一半的数量,但是假如有三台 zookeeper 组成一个集群,那么损坏一台就还剩两台,大于 3 台的一半,所以损坏一台还是可以正常运行的,但是再损坏一台就只剩一台集群就不可用了。那么要是 4 台组成一个zookeeper 集群,损坏一台集群肯定是正常的,那么损坏两台就还剩两台,那么2 台不大于集群数量的一半,所以 3 台的 zookeeper 集群和 4 台的 zookeeper 集群损坏两台的结果都是集群不可用,以此类推 5 台和 6 台以及 7 台和 8 台都是同理,所以这也就是为什么集群一般都是奇数的原因。

集群环境

Zoo1 - 10.0.0.209
Zoo2 - 10.0.0.199
Zoo3 - 10.0.0.189
  1. 三台ZooKeeper安装jdk
apt install openjdk-8-jdk -y
  1. 将ZooKeeper二进制包上传到/apps并解压
mkdir /apps
cd /apps
tar xvf apache-zookeeper-3.5.8-bin.tar.gz
  1. 创建软连接
ln -sv apache-zookeeper-3.5.8-bin/ /apps/zookeeper
  1. 创建ZooKeeper数据目录
mkdir /apps/zookeeper/data
  1. 配置文件修改

拷贝模板文件

cp /apps/zookeeper/conf/zoo_sample.cfg /apps/zookeeper/conf/zoo.cfg

三个服务器的配置文件相同

vim /apps/zookeeper/conf/zoo.cfg
...
dataDir=/apps/zookeeper/data
...
maxClientCnxns=128 #单个客户端IP可以和ZooKeeper保持的连接数
autopurge.snapRetainCount=16
autopurge.purgeInterval=6
server.1=10.0.0.209:2888:3888
server.2=10.0.0.199:2888:3888
server.3=10.0.0.189:2888:3888
tickTime=2000 #服务器与服务器之间的单次心跳检测时间间隔,单位为毫秒
initLimit=10 #集群中 leader 服务器与 follower 服务器初始连接心跳次数,即多少个 2000 毫秒
syncLimit=5 # leader 与 follower 之间连接完成之后,后期检测发送和应答的心跳次数,如果该 follower 在设置的时间内(5*2000)不能与 leader 进行通信,那么此 follower 将被视为不可用。
dataDir=/usr/local/zookeeper/data #自定义的 zookeeper 保存数据的目录
clientPort=2181 #客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求
maxClientCnxns=128 #单个客户端 IP 可以和 zookeeper 保持的连接数
autopurge.snapRetainCount=3 #3.4.0 中的新增功能:启用后,ZooKeeper 自动清除功能会将autopurge.snapRetainCount 最新快照和相应的事务日志分别保留在 dataDir 和 dataLogDir 中,并删除其余部分,默认值为 3。最小值为 3。就是保存快照的数量.
autopurge.purgeInterval=1 # 3.4.0 及之后版本,ZK 提供了自动清理日志和快照文件的功能,这个参数指定了清理频率,单位是小时,需要配置一个 1 或更大的整数,默认是 0,表示不开启自动清理功能
server.1=172.18.0.101:2888:3888 # server.服务器编号=服务器 IP:LF 数据同步端口:LF 选举端口
server.2=172.18.0.102:2888:3888 # leader监听2888
server.3=172.18.0.103:2888:3888 # leader和follower都会监听3888

三个节点分别生成自己的myid文件

root@zoo1:~# echo "1" > /apps/zookeeper/data/myid
root@zoo2:~# echo "2" > /apps/zookeeper/data/myid
root@zoo3:~# echo "3" > /apps/zookeeper/data/myid
  1. 分别启动ZooKeeper
/apps/zookeeper/bin/zkServer.sh start
  1. 查看集群状态

此时可以观察到10.0.0.189被选举为leader

root@Zoo1:/apps/zookeeper/data#  /apps/zookeeper/bin/zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /apps/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower

root@Zoo2:/apps/zookeeper/data#  /apps/zookeeper/bin/zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /apps/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower

root@Zoo3:/apps/zookeeper/data#  /apps/zookeeper/bin/zkServer.sh status
/usr/bin/java
ZooKeeper JMX enabled by default
Using config: /apps/zookeeper/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: leader

root@Zoo1:~# ss -ntl
State                Recv-Q                Send-Q                                      Local Address:Port                                  Peer Address:Port                
LISTEN               0                     128                                         127.0.0.53%lo:53                                         0.0.0.0:*                   
LISTEN               0                     128                                               0.0.0.0:22                                         0.0.0.0:*                   
LISTEN               0                     128                                                  [::]:22                                            [::]:*                   
LISTEN               0                     50                                                      *:2181                                             *:*                   
LISTEN               0                     50                                                      *:37935                                            *:*                   
LISTEN               0                     50                                    [::ffff:10.0.0.209]:3888                                             *:*                   
LISTEN               0                     50                                                      *:8080                                             *:*  
root@Zoo2:~# ss -ntl
State                Recv-Q                Send-Q                                      Local Address:Port                                  Peer Address:Port                
LISTEN               0                     128                                         127.0.0.53%lo:53                                         0.0.0.0:*                   
LISTEN               0                     128                                               0.0.0.0:22                                         0.0.0.0:*                   
LISTEN               0                     50                                                      *:2181                                             *:*                   
LISTEN               0                     50                                                      *:35531                                            *:*                   
LISTEN               0                     50                                    [::ffff:10.0.0.199]:3888                                             *:*                   
LISTEN               0                     50                                                      *:8080                                             *:*                   
LISTEN               0                     128                                                  [::]:22                                            [::]:*     
root@Zoo3:~# ss -ntl
State                Recv-Q                Send-Q                                      Local Address:Port                                  Peer Address:Port                
LISTEN               0                     128                                         127.0.0.53%lo:53                                         0.0.0.0:*                   
LISTEN               0                     128                                               0.0.0.0:22                                         0.0.0.0:*                   
LISTEN               0                     128                                                  [::]:22                                            [::]:*                   
LISTEN               0                     50                                                      *:2181                                             *:*                   
LISTEN               0                     50                                    [::ffff:10.0.0.189]:2888                                             *:*                   
LISTEN               0                     50                                                      *:35053                                            *:*                   
LISTEN               0                     50                                    [::ffff:10.0.0.189]:3888                                             *:*                   
LISTEN               0                     50                                                      *:8080                                             *:* 
  1. 选举过程
  • 节点角色状态
LOOKING:寻找 Leader 状态,处于该状态需要进入选举流程
LEADING:领导者状态,处于该状态的节点说明是角色已经是 Leader
FOLLOWING:跟随者状态,表示 Leader 已经选举出来,当前节点角色是follower
OBSERVER:观察者状态,表明当前节点角色是 observer
  • 选举id
ZXID(zookeeper transaction id):每个改变 Zookeeper 状态的操作都会形成一个对应的 zxid。
myid:服务器的唯一标识(SID),通过配置 myid 文件指定,集群中唯一。
  • 选举过程

当集群中的 zookeeper 节点启动以后,会根据配置文件中指定的 zookeeper 节点地址进行 leader 选择操作,过程如下:

  1. 每个 zookeeper 都会发出投票,由于是第一次选举 leader,因此每个节点都会把自己当做 leader 角色进行选举,每个 zookeeper 的投票中都会包含自己的 myid 和 zxid,此时 zookeeper 1 的投票为 myid 为 1,初始 zxid 有一个初始值,后期会随着数据更新而自动变化,zookeeper2 的投票为 myid 为 2,初
    始 zxid 为初始生成的值。
  2. 每个节点接受并检查对方的投票信息,比如投票时间、是否状态为 LOOKING状态的投票。
  3. 对比投票,优先检查 zxid,如果 zxid不一样则 zxid大的为 leader,如果 zxid相同则继续对比 myid,myid 大的一方为 leader

成为 Leader 的必要条件: Leader 要具有最高的 zxid;当集群的规模是 n 时,
集群中大多数的机器(至少 n/2+1)得到响应并 follow 选出的 Leader。

心跳机制:Leader 与 Follower 利用 PING 来感知对方的是否存活,当 Leader 无
法响应 PING 时,将重新发起 Leader 选举。

新集群, 由于没有数据, zxid在各个节点相同, 因此, 一般会比较myid, 集群运行后, zxid会随着数据的插入而发生变化, 哪个节点的数据越新, zxid值就会越大, 就会被选举为leader

  1. 各节点的选择日志
cat /apps/zookeeper/logs/zookeeper-root-server-Zoo3.out
  1. 测试数据同步

分别在三台节点, 通过命令行工具连接到本地ZooKeeper

/apps/zookeeper/bin/zkCli.sh

zoo1上创建数据

[zk: localhost:2181(CONNECTED) 0] create /test "hello" # 通过命令行是无法递归创建目录的
Created /test

zoo2查看

[zk: localhost:2181(CONNECTED) 0] get /test
hello

zoo3查看

[zk: localhost:2181(CONNECTED) 0] get /test
hello
  1. ZooKeeper数据存放

ZooKeeper数据存放在配置文件中定义的数据目录下的version-x/log文件里, 因此要对数据目录做定期备份
由于三个服务器的数据都是相同的, 因此备份一个客户端的即可

cat /apps/zookeeper/data/version-2/log.100000001 
ZKLG"$*,pvf¦ÿN=$V8Pvf§C@ÿÿÿ|c $ vf§Hu0B&
                                                    R*,pvf©A/testhelloworldanyoneB 

  1. ZooKeeper监控
  • Zabbix监控各个节点的各个端口
  • 执行客户端zkCli.sh命令, 进入ZooKeeper,再退出, 检查命令是否执行成功
  1. Zookeeper客户端在Linux平台使用
  • 客户端编译
root@zooinsepect:~# apt install git maven openjdk-8-jdk -y
root@zooinsepect:~# git clone https://github.com/zzhang5/zooinspector.git
root@zooinsepect:~# cd /zooinspector
root@zooinsepect:~/zooinspector# mvn clean package
图片.png
  • 客户端使用
root@Zoo1:~/zooinspector# chmod +x target/zooinspector-pkg/bin/zooinspector.sh
root@Zoo1:~/zooinspector# export DISPLAY=10.0.0.1:0.0

Windows开启Xmanager

修改xshell配置

图片.png
root@Zoo1:~/zooinspector# target/zooinspector-pkg/bin/zooinspector.sh
图片.png
图片.png

你可能感兴趣的:(4. ZooKeeper)