• ZooKeeper集群操作以及集群Master选举


    ZooKeeper介绍

    ZooKeeper 是一个为 分布式应用 提供的 分布式 、开源的 协调服务

    它公开了一组简单的 原语分布式应用程序可以根据这些原语来实现用于 同步配置维护 以及 命名 的更高级别的服务。

    怎么理解协调服务呢?比如我们有很多应用程序,他们之间都需要读写维护一个 id ,那么这些 id 怎么命名呢,程序一多,必然会乱套,ZooKeeper 能协调这些服务,解决命名、配置、同步等问题,而做到这些,只需要一组简单的 原语 即可:

    1. create : 在树中的某个位置创建一个节点
    2. delete : 删除一个节点
    3. exists : 测试节点是否存在于某个位置
    4. get data : 从节点读取数据
    5. set data : 往一个节点里写入数据
    6. get children : 检索节点的子节点列表
    7. sync : 等待数据被传播
    8. 复制代码

    从这些 ZooKeeper (以下简称ZK)的 API 可以看到,都是围绕 Node 来操作,下文实操看一下怎么操作 Node

    ZooKeeper 的特征

    • 简单

    ZooKeeper 允许分布式进程通过 共享的层级命名空间 相互协调,该命名空间的组织类似于标准文件系统。

    命名空间由 数据寄存器 组成,在 ZooKeeper 称为 znodes ,它们类似于文件和目录。

    与典型的文件系统不同,它是为 存储 而设计的,ZooKeeper 数据保存在 内存 中,这意味着ZooKeeper 可以实现 高吞吐量低延迟数

    ZooKeeper 很重视 高性能高可用性严格有序访问 :性能高意味着它可以在大型分布式系统中使用;而他又具备可靠性,这使它不会成为单点故障;严格的排序意味着可以在客户端上实现复杂的同步原语。

    • 可被复制(高可用)

    像它协调的分布式进程一样,ZooKeeper 本身也可以在称为集合的一组主机上进行复制。

    组成ZooKeeper 服务的服务器都必须彼此了解。它们维护内存中的状态镜像,以及持久存储中的事务日志和快照。只要大多数服务器可用,ZooKeeper 服务将可用。

    客户端连接到单个 ZooKeeper 服务器。客户端维护一个 TCP连接 ,通过该连接发送请求,获取响应,获取监视事件并发送心跳。如果与服务器的 TCP连接 断开,则客户端将连接到其他服务器。

    • 有序的

    ZooKeeper 用一个反映所有 ZooKeeper 事务顺序 的数字标记每个更新。后续操作可以使用该命令来实现更高级别的抽象,例如 同步分布式锁

    读取为主 的工作负载中,它特别快。

    ZooKeeper 应用程序可在数千台计算机上运行,并且在读取比写入更常见的情况下,其性能最佳,比率约为10:1。

    分层命名空间

    ZooKeeper提供的名称空间与标准文件系统的名称空间非常相似。

    名称是由 斜杠/)分隔的一系列路径元素。ZooKeeper 命名空间中的每个节点均由路径标识。

    一个 ZK Node 可以存储 1M 数据,Node分为 持久节点临时性节点

    • 持久节点

    与标准文件系统不同,ZooKeeper 命名空间中的每个节点都可以具有与其关联的 数据 以及 子节点 。就像拥有一个文件系统一样,该文件系统也允许文件成为目录。

    ZooKeeper旨在存储协调数据:状态信息,配置,位置信息等,因此存储在每个节点上的数据通常很小,在字节到千字节范围内。

    Znodes 维护一个统计信息结构,其中包括用于 数据更改ACL更改(权限控制)时间戳的版本号 ,以允许进行 缓存验证协调更新

    Znode 的数据每次更改时,版本号都会增加。例如,每当客户端检索数据时,它也会接收数据的版本。

    原子地读取和写入存储在名称空间中每个 Znode 上的数据。读取将获取与znode关联的所有数据字节,而写入将替换所有数据。每个节点都有一个访问控制列表(ACL),用于限制谁可以做什么。

    • 临时节点

    只要创建 Znode 的会话处于 活动状态 ,这些 Znode 就一致存在。会话结束时,将删除 Znode ,这就是临时节点。

    类比于web容器比如tomcat的session,创建临时节点的session存在,则node存在,session结束,删除node。

    以上是理论知识,还是实际操作一遍比较靠谱,理解一下zk创建连接、node、session这些概念,以及看看zk集群的leader出故障后,选出leader的速度。

    搭建ZK集群

    首先准备 4 台 CentOS 7 虚拟机,都安装好了JDK 8(JDK版本最好不要小于8)。

    这四台虚拟机主机名称分别设置为:zknode01zknode02zknode03zknode04

    1. hostnamectl set-hostname zknode01
    2. 复制代码

    主机名在配置 ZooKeeper 集群的时候有用。

    主机名称配置好之后,还需要配置主机名和IP地址的映射关系,每台主机均编辑 /etc/hosts 文件,末尾添加如下内容:

    1. 192.168.242.11 zknode01
    2. 192.168.242.12 zknode02
    3. 192.168.242.13 zknode03
    4. 192.168.242.14 zknode04
    5. 复制代码

    保证每台主机都能互相 ping 通:

    接下来,先安装配置好其中一台服务器的 ZooKeeper ,然后用 scp 分发到各个服务器,再分别修改 zk serverid ,这样不用每台虚拟机都执行一遍相同的操作。

    下载zk,注意一定要是apache-zookeeper-3.7.1-bin.tar.gz这个带bin的,否则如果不是带bin的,启动的时候会报如下错误:

    1. Error: Could not find or load main class org.apache.zookeeper.server.quorum.QuorumPeerMain
    2. Caused by: java.lang.ClassNotFoundException: org.apache.zookeeper.server.quorum.QuorumPeerMain
    3. 复制代码

    保姆式安装zk步骤:

    1. 将下载好的 apache-zookeeper-3.7.1-bin.tar.gz 放到/opt目录下
    2. 1. cd /opt
    3. 2. tar xf apache-zookeeper-3.7.1-bin.tar.gz
    4. 3. mv apache-zookeeper-3.7.1-bin zookeeper
    5. 4. vi /etc/profile
    6. export JAVA_HOME=/usr/local/java
    7. export ZK_HOME=/opt/zookeeper
    8. export PATH=$PATH:$JAVA_HOME/bin:$ZK_HOME/bin
    9. 5. source /etc/profile
    10. 6. cd /opt/zookeeper/conf
    11. 7. cp zoo_sample.cfg zoo.cfg
    12. 8. vi zoo.cfg
    13. 设置 dataDir=/var/zookeeper
    14. 末尾添加:
    15. server.1=zknode01:2888:3888
    16. server.2=zknode02:2888:3888
    17. server.3=zknode03:2888:3888
    18. server.4=zknode04:2888:3888
    19. 9. mkdir -p /var/zookeeper
    20. 10. echo 1 > /var/zookeeper/myid
    21. 复制代码

    这样 zknode01 的 zkserver 就搭建好了,现在将 ZooKeeper目录配置文件 分发到其余三台服务器:

    1. # 传到 zknode02
    2. scp -r /opt/zookeeper/ root@zknode02:/opt/
    3. scp /etc/profile root@zknode02:/etc
    4. # 传到 zknode03
    5. scp -r /opt/zookeeper/ root@zknode03:/opt/
    6. scp /etc/profile root@zknode03:/etc
    7. # 传到 zknode04
    8. scp -r /opt/zookeeper/ root@zknode04:/opt/
    9. scp /etc/profile root@zknode04:/etc
    10. 复制代码

    别忘了 ,每台主机都需要执行 source /etc/profile 和创建 /var/zookeeper/myid 文件,myid 的内容分别为 2,3,4 。

    这样 zk集群 就搭建好了。

    启动zk集群

    按顺序启动 zknode01zknode02zknode03zknode04 的zk服务:

    1. zkServer.sh start-foreground
    2. 复制代码

    zk默认后台启动, start-foreground 表示前台启动,方便看日志。

    启动zknode01的zk server:

    会报错,因为 zoo.cfg 配置了4台主机,其余三台还未启动,接着启动 zknode02 的:

    现象同 zknode01 ,继续启动第三台:

    这个时候也会报 zknode04 连接不上(因为还没启动),但是整个 zk集群 已经启动了,并且选择了 zknode03 这个为leader。

    zknode04 也启动一下:

    启动完成后,开一个 zknode01 的zk客户端:

    1. zkCli.sh
    2. [zk: localhost:2181(CONNECTED) 0] help
    3. ZooKeeper -server host:port -client-configuration properties-file cmd args
    4. addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE
    5. addauth scheme auth
    6. close
    7. config [-c] [-w] [-s]
    8. connect host:port
    9. create [-s] [-e] [-c] [-t ttl] path [data] [acl]
    10. delete [-v version] path
    11. deleteall path [-b batch size]
    12. delquota [-n|-b] path
    13. get [-s] [-w] path
    14. getAcl [-s] path
    15. getAllChildrenNumber path
    16. getEphemerals path
    17. history
    18. listquota path
    19. ls [-s] [-w] [-R] path
    20. printwatches on|off
    21. quit
    22. 复制代码

    用上面的命令操作一波:

    1. [zk: localhost:2181(CONNECTED) 1] ls
    2. ls [-s] [-w] [-R] path
    3. [zk: localhost:2181(CONNECTED) 2] ls /
    4. [zookeeper]
    5. [zk: localhost:2181(CONNECTED) 3]
    6. [zk: localhost:2181(CONNECTED) 3] create /laogong
    7. Created /laogong
    8. [zk: localhost:2181(CONNECTED) 4] ls /
    9. [laogong, zookeeper]
    10. [zk: localhost:2181(CONNECTED) 5] get /laogong
    11. null
    12. [zk: localhost:2181(CONNECTED) 6] create /laogong "laogong"
    13. Node already exists: /laogong
    14. [zk: localhost:2181(CONNECTED) 7] delete /laogong
    15. [zk: localhost:2181(CONNECTED) 8] ls /
    16. [zookeeper]
    17. [zk: localhost:2181(CONNECTED) 9] create /laogong "laogong"
    18. Created /laogong
    19. [zk: localhost:2181(CONNECTED) 10] ls /
    20. [laogong, zookeeper]
    21. [zk: localhost:2181(CONNECTED) 11] get /laogong
    22. laogong
    23. [zk: localhost:2181(CONNECTED) 12] create /laogong/laopo "laopo"
    24. Created /laogong/laopo
    25. [zk: localhost:2181(CONNECTED) 13] ls /
    26. [laogong, zookeeper]
    27. [zk: localhost:2181(CONNECTED) 14] ls /laogong
    28. [laopo]
    29. [zk: localhost:2181(CONNECTED) 15] get /laogong/laopo
    30. laopo
    31. [zk: localhost:2181(CONNECTED) 16]
    32. 复制代码

    上面的操作我都是在 zknode01 上面连接zk进行操作的,来看一下,在其他zkserver上有没有同步过来数据:

    发现数据已经同步,zknode03zknode04 数据也同步了。

    再来看一下连接 zknode02 的连接状态:

    1. [root@zknode02 ~]# netstat -natp | egrep '(2888|3888)'
    2. tcp6 0 0 192.168.242.12:3888 :::* LISTEN 9530/java
    3. tcp6 0 0 192.168.242.12:3888 192.168.242.13:47474 ESTABLISHED 9530/java
    4. tcp6 0 0 192.168.242.12:37804 192.168.242.13:2888 ESTABLISHED 9530/java
    5. tcp6 0 0 192.168.242.12:3888 192.168.242.14:47530 ESTABLISHED 9530/java
    6. tcp6 0 0 192.168.242.12:39666 192.168.242.11:3888 ESTABLISHED 9530/java
    7. 复制代码

    连接状态分析:

    上图是从 zknode02 服务器查看的,通过查看每台服务器,最终,zk集群的服务器每台都 互相通信

    这个 3888 端口就是选举master用的,而 2888 端口是leader接受write请求用的。

    zk集群master选举

    前面演示了有 4 个服务器的 zk集群 ,其中 zknode03 是 leader 。

    现在我把 zknode03 服务干掉:

    1. ^C[root@zknode03 conf]# zkServer.sh status
    2. ZooKeeper JMX enabled by default
    3. Using config: /opt/zookeeper/bin/../conf/zoo.cfg
    4. Client port found: 2181. Client address: localhost. Client SSL: false.
    5. Error contacting service. It is probably not running.
    6. [root@zknode03 conf]#
    7. [root@localhost ~]#
    8. 复制代码

    再来分别看一下 zknode01 ~ zknode04的 zk server 状态:

    可以看到 zknode04 自动成了 leader !

    事实上,zk集群 选举 leader 采用的是 谦让 的办法,谁的 id 大,选举谁。

    那么前面为什么zknode3是leader呢?

    因为我启动的顺序是 zknode01 ~ zknode04 启动的,当 zknode03 的zk server 启动的时候,已经 满足集群的最少节点数 了,而且 zknode03 的 id 是 当时 最大的,所以 zknode03 的 server自动成了 leader 。


     

  • 相关阅读:
    leetCode 674. 最长连续递增序列 动态规划 / 贪心策略
    2.6、物理层-真题
    初入Vue(二)-vue.config.js
    如何在雷电模拟器上安装Magisk并加载movecert模块抓https包(一)
    XFINIUM.PDF CROSS-PLATFORM BUNDLE 11.1.2
    CardView设置任意角为圆角
    v-model和.sync区别
    Zookeeper经典应用场景实战(二)
    Tomcat部署war包项目请求404
    nodejs毕业设计源码中介房屋租赁管理系统
  • 原文地址:https://blog.csdn.net/m0_71777195/article/details/126247304