4. ZooKeeper

作者: 随便写写咯 | 来源:发表于2021-06-28 18:01 被阅读0次

    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§H񁀶u0B&
                                                        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

        本文链接:https://www.haomeiwen.com/subject/kecvgktx.html