Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper

Zookeeper 入门 1.1 概述 Zookeeper是一个开源的分布式的,为分布式框架提供协调服务的 Apache 项目。
Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

  • 工作机制
    • Zookeeper从设计模式角度来理解:
      是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将负责通知已经在Zookeeper上注册的那些观察者做出相应的反应。
Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

1.2特点 Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

1.3数据结构 ZooKeeper 数据模型的结构与 Unix 文件系统很类似,整体上可以看作是一棵树,每个节点称做一个 ZNode。每一个 ZNode 默认能够存储 1MB 的数据,每个 ZNode 都可以通过其路径唯一标识
Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

1.4应用场景 提供的服务包括:统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡等。
  • 统一命名服务
在分布式环境下,经常需要对应用/服务进行统一命名,便于识别。例如:IP不容易记住,而域名容易记住
Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

  • 统一配置管理
    • 分布式环境下,配置文件同步非常常见。
      • (1)一般要求一个集群中,所有节点的配置信息是一致的,比如 Kafka 集群。
      • (2)对配置文件修改后,希望能够快速同步到各个节点上。
    • 配置管理可交由ZooKeeper实现。
      • (1)可将配置信息写入ZooKeeper上的一个Znode。
      • (2)各个客户端服务器监听这个Znode。
      • (3)一旦Znode中的数据被修改,ZooKeeper将通知各个客户端服务器。
    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

  • 统一集群管理
    • 分布式环境中,实时掌握每个节点的状态是必要的。
      • (1)可根据节点实时状态做出一些调整。
    • ZooKeeper可以实现实时监控节点状态变化
      • (1)可将节点信息写入ZooKeeper上的一个ZNode。
      • (2)监听这个ZNode可获取它的实时状态变化。
Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

  • 服务器动态上下线
Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

  • 软负载均衡
在Zookeeper中记录每台服务器的访问数,让访问数最少的服务器去处理最新的客户端请求
Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

1.5下载地址
  • 1) 官网首页:
    https://zookeeper.apache.org/
  • 2)
    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

  • 3 )下载 Linux 环境安装的 tar包
    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

Zookeeper 本地安装 2.1 本地模式 安装
  • 安装前准备
  • (1)安装 JDK
  • (2)拷贝 apache-zookeeper-3.5.7-bin.tar.gz 安装包到 Linux 系统下
  • (3)解压到指定目录
    tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz

  • (4)修改名称
    mv apache-zookeeper-3.5.7 -bin/zookeeper-3.5.7

  • 配置修改
    • (1)将/usr/local/zookeeper/zookeeper-3.5.7/conf 这个路径下的 zoo_sample.cfg 修改为 zoo.cfg;
      mv zoo_sample.cfg zoo.cfg

    • (2)打开 zoo.cfg 文件,修改 dataDir 路径:
      vim zoo.cfg

      修改如下内容:
      dataDir=/usr/local/zookeeper/zkData

      Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
      文章图片

    • (3)在/usr/local/zookeeper/zookeeper-3.5.7/这个目录上创建 zkData 文件夹
      mkdir zkData

  • 操作 Zookeeper
    • 启动 Zookeeper
    bin/zkServer.sh start

    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

    • 查看进程是否启动
    jps

    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

    • 查看状态
    bin/zkServer.sh status

    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

    • 启动客户端
    bin/zkCli.sh

    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

    • 退出客户端
      Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
      文章图片

    quit

    • 停止 Zookeeper
    bin/zkServer.sh stop

    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

2.2 配置参数 Zookeeper中的配置文件zoo.cfg中参数含义解读如下:
Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

  • tickTime = 2000:
    通信心跳时,Zookeeper 服务器与客户端心跳时间,单位毫秒
    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

  • initLimit = 10 :
    Leader和Follower的初始通信时限
    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

    Leader和Follower初始连接时能容忍的最多心跳数(tickTime的数量)
  • syncLimit = 5 :
    LF 同步通信时限
    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

    Leader和Follower之间通信时间如果超过syncLimit * tickTime,Leader认为Follwer死掉,从服务器列表中删除Follwer。
  • dataDir :
    保存Zookeeper中的数据
    注意:默认的tmp目录,容易被Linux系统定期删除,所以一般不用默认的tmp目录。
  • clientPort = 2181 :
    客户端连接端口 ,通常不做修改。
Zookeeper 集群操作 3.1 集群操作 3.1.1 集群安装
  • 集群规划
    在 hadoop102、hadoop103 和 hadoop104 三个节点上都部署 Zookeeper。
    思考:如果是 10 台服务器,需要部署多少台 Zookeeper ?
  • 解压安装
    重复上面的单机安装过程
  • 配置服务器编号
    • (1)在创建 zkData
      mkdir zkData

    • (2)在zkData 目录下创建一个 myid 的文件
      touch myid vi myid

      在文件中添加与 server 对应的编号(注意:上下不要有空行,左右不要有空格)
      2

      注意:添加 myid 文件,一定要在 Linux 里面创建,在 notepad++里面很可能乱码
    • (3)拷贝配置好的 zookeeper 到其他机器上
      xsync zookeeper-3.5.7

      并分别在 hadoop103、hadoop104 上修改 myid 文件中内容为 3、4
  • 配置zoo.cfg 文件
  • (1)如上一样重命名zoo_sample.cfg 为zoo.cnf
  • (2)打开 zoo.cfg 文件
    vim zoo.cfg

    • #修改数据存储路径配置
      dataDir=/usr/local/zookeeper/zkData

    • #增加如下配置
      #######################cluster########################## server.1=192.168.109.101:2888:3888 server.2=192.168.109.102:2888:3888 server.3=192.168.109.103:2888:3888

      Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
      文章图片

  • (3)配置参数解读
    server.A=B:C:D。

    • A 是一个数字,表示这个是第几号服务器;
      集群模式下配置一个文件 myid,这个文件在 dataDir 目录下,这个文件里面有一个数据就是 A 的值,Zookeeper 启动时读取此文件,拿到里面的数据与 zoo.cfg 里面的配置信息比较从而判断到底是哪个 server
    • B 是这个服务器的地址;
    • C 是这个服务器 Follower 与集群中的 Leader 服务器交换信息的端口;
    • D 是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
  • (4)同步 zoo.cfg 配置文件
    xsync zoo.cfg

  • 集群操作
  • (1)分别启动 Zookeeper
    bin/zkServer.sh start #s1 bin/zkServer.sh start #s2 bin/zkServer.sh start #s3

  • (2)查看状态
    [root@s1 zookeeper3.5.7]# sh bin/zkServer.sh status ZooKeeper JMX enabled by default Using config: /usr/local/zookeeper/zookeeper3.5.7/bin/../conf/zoo.cfg Client port found: 2181. Client address: localhost. Mode: follower[root@s2 zookeeper3.5.7]# sh bin/zkServer.sh status ZooKeeper JMX enabled by default Using config: /usr/local/zookeeper/zookeeper3.5.7/bin/../conf/zoo.cfg Client port found: 2181. Client address: localhost. Mode: follower[root@s3 zookeeper3.5.7]# sh bin/zkServer.sh status ZooKeeper JMX enabled by default Using config: /usr/local/zookeeper/zookeeper3.5.7/bin/../conf/zoo.cfg Client port found: 2181. Client address: localhost. Mode: leader

3.1.2 选举机制(面试重点)
  • Zookeeper选举机制—— 第一次启动
总结一句话,后来者居上
Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

  • Zookeeper选举机制——非第一次启动
Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

3.1.3 ZK 集群启动停止脚本
  • 1)在 hadoop102 的/home/atguigu/bin 目录下创建脚本
    #!/bin/bash case $1 in "start"){for i in 192.168.109.101 192.168.109.102 192.168.109.103 do echo ---------- zookeeper $i 启动 ------------ ssh $i "sh /usr/local/zookeeper/zookeeper3.5.7/bin/zkServer.sh start" done }; ; "stop"){for i in 192.168.109.101 192.168.109.102 192.168.109.103 do echo ---------- zookeeper $i 停止 ------------ ssh $i "sh /usr/local/zookeeper/zookeeper3.5.7/bin/zkServer.sh stop" done }; ; "status"){for i in 192.168.109.101 192.168.109.102 192.168.109.103 do echo ---------- zookeeper $i 状态 ------------ ssh $i "sh /usr/local/zookeeper/zookeeper3.5.7/bin/zkServer.sh status" done }; ; esac

  • 2)增加脚本执行权限
    chmod u+x zk.sh

  • Zookeeper 集群启动脚本
    ./zk.sh start

  • Zookeeper 集群停止脚本
    ./zk.sh stop

3.2 客户端 命令行 操作 3.2.1 命令行语法
命令基本语法 功能描述
help 显示所有操作命令
ls path 使用 ls 命令来查看当前 znode 的子节点 [可监听]
-w 监听子节点变化
-s 附加次级信息
create 普通创建
-s 含有序列
-e 临时(重启或者超时消失)
get path 获得节点的值 [可监听]
-w 监听节点内容变化
-s 附加次级信息
set 设置节点的具体值
stat 查看节点状态
delete 删除节点
deleteall 递归删除节点
  • 1) 启动客户端
    bin/zkCli.sh -server 192.168.109.101:2181

    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

  • 2) 显示所有操作命令
    help

3.2.2 znode 节点数据信息
  • 1) 查看当前znode 中所包含的内容
ls /

  • 2) 查看当前节点详细 数据
    ls -s /

    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

    • czxid:
      • 创建节点的事务 zxid每次修改 ZooKeeper 状态都会产生一个 ZooKeeper 事务 ID。事务 ID 是 ZooKeeper 中所有修改总的次序。
      • 每次修改都有唯一的 zxid,如果 zxid1 小于 zxid2,那么 zxid1 在 zxid2 前发生。
    • ctime:
      • znode 被创建的毫秒数(从 1970 年开始)
    • mzxid:
      • znode 最后更新的事务 zxid
    • mtime:
      • znode 最后修改的毫秒数(从 1970 年开始)
    • pZxid:
      • znode 最后更新的子节点 zxid
    • cversion:
      • znode 子节点变化号,znode 子节点修改次数
    • dataversion:
      • znode 数据变化号
    • aclVersion:
      • znode 访问控制列表的变化号
    • ephemeralOwner:
      • 如果是临时节点,这个是 znode 拥有者的 session id。如果不是临时节点则是 0。
    • dataLength:
      • znode 的数据长度
    • numChildren:
      • znode 子节点数量
3.2.3 节点类型 (持久/ 短暂/ 有序号/ 无序号)
  • 节点类型
    Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
    文章图片

    • 1) 分别创建2 个普通节点 (永久节点 + 不带序号)
    create /sanguo "diaochan"

    注意:创建节点时,要赋值
    • 2)获得节点的值
    get -s /sanguo

    • 3)创建带序号的节点 (永久节点 + 带序号)
      • (1)先创建一个普通的根节点/sanguo/weiguo
      create /sanguo/weiguo"caocao"

      • (2)创建带序号的节点
      create -s /sanguo/weiguo/zhangliao "zhangliao"

      如果原来没有序号节点,序号从 0 开始依次递增。如果原节点下已有 2 个节点,则再排序时从 2 开始,以此类推。
    • 4) 创建短暂节点 (短暂节点 + 不带序号 or 带序号)
      • (1)创建短暂的不带序号的节点
      create -e /sanguo/wuguo"zhouyu"

      • (2)创建短暂的带序号的节点
      create -e -s /sanguo/wuguo"zhouyu"

      • (3)在当前客户端是能查看到的
      ls /sanguo

      • (4)退出当前客户端然后再重启客户端
      quit

      • (5)再次查看根目录下短暂节点已经删除
      set /sanguo/weiguo "simayi"

3.2.4 监听器原理
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、节点删除、子目录节点增加删除)时,ZooKeeper 会通知客户端。监听机制保证 ZooKeeper 保存的任何的数据的任何改变都能快速的响应到监听了该节点的应用程序。
Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

  • 1)节点的值变化监听
    • (1)在 192.168.109.103主机上注册监听/sanguo 节点数据变化
    get -w /sanguo

    • (2)在 192.168.109.102主机上修改/sanguo 节点的数据
    set /sanguo "xisi"

    • (3)观察 192.168.109.103主机收到数据变化的监听
    WATCHER:: WatchedEvent state:SyncConnected type:NodeDataChanged path:/sanguo

    注意:在192.168.109.102再多次修改/sanguo的值,192.168.109.103上不会再收到监听。因为注册一次,只能监听一次。想再次监听,需要再次注册。
  • 2)节点的子节点变化监听(路径变化)
    • (1)在 192.168.109.103主机上注册监听/sanguo 节点的子节点变化
    ls -w /sanguo

    • (2)在 192.168.109.102 主机/sanguo 节点上创建子节点
    create /sanguo/jin "simayi"

    • (3)观察 192.168.109.103主机收到子节点变化的监听
    WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/sanguo

    注意:节点的路径变化,也是注册一次,生效一次。想多次生效,就需要多次注册。
3.2.5 节点删除与查看
  • 1) 删除节点
delete /sanguo/jin

  • 2) 递归删除节点
deleteall /sanguo/shuguo

  • 3) 查看节点状态
stat /sanguo

3.3 客户端 API 操作 3.3.1 IDEA 环境
前提:保证 192.168.109.101、192.168.109.102、192.168.109.103服务器上 Zookeeper 集群服务端启动。
  • 1) 创建一个 工程: :zookeeper
  • 2) 添加pom
junit junit RELEASE org.apache.logging.log4j log4j-core 2.8.2 org.apache.zookeeper zookeeper 3.5.7

  • 3) 拷贝log4j.properties 文件到项目根目录
需要在项目的 src/main/resources 目录下,新建一个文件,命名为“log4j.properties”,在文件中填入。
log4j.rootLogger=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c]- %m%n log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=target/spring.log log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d %p [%c]- %m%n

  • 4 )创建包名com.achang.zk
  • 5 )创建类名称zkClient
3.3.2 创建 ZooKeeper 客户端
// 注意:逗号前后不能有空格 private static String connectString = "192.168.109.101:2181,192.168.109.102:2181,192.168.109.103:2181"; private static int sessionTimeout = 2000; private ZooKeeper zkClient = null; @Before public void init() throws Exception {zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {@Override public void process(WatchedEvent watchedEvent) {// 收到事件通知后的回调函数(用户的业务逻辑) System.out.println(watchedEvent.getType() + "--" + watchedEvent.getPath()); // 再次启动监听 try {List children = zkClient.getChildren("/", true); for (String child : children) {System.out.println(child); } } catch (Exception e) {e.printStackTrace(); } } }); }

3.3.3 创建子节点
// 创建子节点 @Test public void create() throws Exception {// 参数 1:要创建的节点的路径; 参数 2:节点数据 ; 参数 3:节点权限 ;参数 4:节点的类型 String nodeCreated = zkClient.create("/achang","shuaige".getBytes(),Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT); }

测试:在 192.168.109.101的 zk 客户端上查看创建节点情况
[zk: localhost:2181(CONNECTED) 16] get -s /achang shuaige

3.3.4 获取 子节点 并 监听 节点 变化
// 获取子节点 @Test public void getChildren() throws Exception {List children = zkClient.getChildren("/", true); for (String child : children) {System.out.println(child); } // 延时阻塞 Thread.sleep(Long.MAX_VALUE); }

  • (1)在 IDEA 控制台上看到如下节点:
zookeeper sanguo achang

  • (2)在 192.168.109.101的客户端上创建再创建一个节点/achang1,观察 IDEA 控制台
create /achang1 "achang1"

  • (3)在 192.168.109.101的客户端上删除节点/achang1,观察 IDEA 控制台
delete /achang1

3.3.5 判断 Znode 是否存在
// 判断 znode 是否存在 @Test public void exist() throws Exception {Stat stat = zkClient.exists("/achang", false); System.out.println(stat == null ? "not exist" : "exist"); }

3.4 客户端向服务端写数据流程
  • 写流程之写入请求直接发送给Leader节点
Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

  • 写流程之写入请求发送给follower节点
【Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper】Zookeeper|Day375&376.Zookeeper入门&单机安装&集群操作 -Zookeeper
文章图片

    推荐阅读