Zookeeper学习笔记

Zookeeper学习

ZooKeeper(动物园管理者)简称ZK,一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。ZooKeeper使用Java 所编写,但是支持Java和C两种编程语言。

协调服务

  • dubbo框架 springcloud框架 zk 注册中心

  • Hadoop Hbase组件﹐集群架构﹑ zk集群管理者

  • zk实现分布式锁

内存数据模型

模型结构

在这里插入图片描述

2.模型的特点

  • 每个子目录如/node1都被称作一个znode(节点)。这个znode是被它所在的路径唯一标识
  • znode可以有子节点目录,并且每个znode 可以存储数据
  • znode是有版本的,每个znode中存储的数据可以有多个版本,也就是一个访问路径中可以存储多份数据
  • znode可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端

节点的分类

持久节点(PERSISTENT)

是指在节点创建后,就一直存在,直到有删除操作来主动删除这个节点――不会因为创建该节点的客户端会话失效而消失

持久顺序节点(PERSISTENT_SEQUENTIAL)

这类节点的基本特性和上面的节点类型是一致的。额外的特性是,在ZK中,每个父节点会为他的第一级子节点维护一份时序,会记录每个子节点创建的先后顺序。基于这个特性,在创建子节点的时候,可以设置这个属性,那么在创建节点过程中,ZK会自动为给定节点名加上一个数字后缀,作为新的节点名。这个数字后缀的范围是整型的最大值。

临时节点(EPHEMERAL)

和持久节点不同的是,临时节点的生命周期和客户端会话绑定。也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉。注意,这里提到的是会话失效,而非连接断开。另外,在临时节点下面不能创建子节点

临时顺序节点(EPHEMERAL_SEQUENTIAL)

具有临时节点特点,额外的特性是,每个父节点会为他的第一级子节点维护一份时序。这点和刚才提到的持久顺序节点类似

起名字按首字母 分别是 P 、 PS、 E、 ES

安装

手动安装

1.安装jdk8

2.解压zookeeper-3.4.12.tar.gz
tar -zxvf zookeeper-3.4.12.tar.gz

3.配置  进入 conf目录  有个模板文件 复制一份并重新命名
cp zoo_sample.cfg zoo.cfg
可以看到默认端口2181

tickTime:集群节点之间的的心跳  默认每2s

initLimit:初始化限制  初始化集群时  集群节点同步超时时间  默认10*(tickTime) = 20s

syncLimit:集群运行过程中 同步超时时间  默认5*(tickTime) = 10s

dataDir: 默认存储数据的位置
clientPort:默认端口号
maxClientCnxns: 线程池的数量(最大客户端连接数)  默认60

在这里插入图片描述

4. 启动服务  后面需要更上配置文件
./zkServer.sh start /root/zookeeper-3.4.12/conf/zoo.cfg
./zkServer.sh stop /root/zookeeper-3.4.12/conf/zoo.cfg  关闭服务
ZooKeeper JMX enabled by default
Using config: /root/zookeeper-3.4.12/conf/zoo.cfg
Starting zookeeper ... STARTED

5.使用jps查看是否启动
[root@localhost bin]# jps
1412 QuorumPeerMain
1429 Jps

6.使用客户端命令查看是否正常运行
./zkCli.sh -server 192.168.29.133:2181

7.测试以下命令
[zk: 192.168.29.133:2181(CONNECTED) 0] ls /
[zookeeper]

Docker安装zookeeper

​ 获取zk的镜像

  • docker pull zookeeper : 3.4.14

    启动zk服务

  • docker run --name zk -p 2181:2181 -d zookeeper :3.4.14

客户端基本指令

ZooKeeper -server host:port cmd args
        stat path [watch]
        set path data [version]
        ls path [watch]
        delquota [-n|-b] path
        ls2 path [watch]
        setAcl path acl
        setquota -n|-b val path
        history 
        redo cmdno
        printwatches on|off
        delete path [version]
        sync path
        listquota path
        rmr path
        get path [watch]
        create [-s] [-e] path data acl
        addauth scheme auth
        quit 
        getAcl path
        close 
        connect host:port

常用总结:

--查看该路径下的节点
ls 路径   

--创建一个节点
create 节点 数据
create /node1 zhangan  			默认 持久节点
create -s /node1 zhangan  		顺序节点
create -e /node1 zhangan  		临时节点
create -s -e /node1 zhangan  	临时顺序节点

--查看节点状态
stat 节点

[zk: 192.168.29.133:2181(CONNECTED) 12] stat /node1
cZxid = 0x4  创建id
ctime = Mon Jun 07 16:18:20 CST 2021  创建时间
mZxid = 0x4  修改
mtime = Mon Jun 07 16:18:20 CST 2021   修改时间
pZxid = 0x4  父节点id
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0   
dataLength = 7
numChildren = 0

--获取节点数据
get 节点

[zk: 192.168.29.133:2181(CONNECTED) 13] get /node1
zhangan
cZxid = 0x4
ctime = Mon Jun 07 16:18:20 CST 2021
mZxid = 0x4
mtime = Mon Jun 07 16:18:20 CST 2021
pZxid = 0x4
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 0

--修改数据
set 节点 数据

--历史记录
history

--删除节点
delete  节点   只能删除没有子节点的

--递归删除
rmr 节点  

--推出会话(会话失效)
quit

watch节点监听机制

客户端可以监测znode节点的变化。Zonode节点的变化触发相应的事件,然后清除对该节点的监测。当监测一个znode节点时候,Zookeeper会发送通知给监测节点。一个Watch事件是一个一次性的触发器,当被设置了Watch的数据和目录发生了改变的时候,则服务器将这个改变发送给设置了Watch的客户端以便通知它们。

1s /path true
监听节点目录的变化
get /path true
监听节点数据的变化。

Java操作ZK

引入依赖

<dependency>
    <groupId>com.101tec</groupId>
    <artifactId>zkclient</artifactId>
    <version>0.10</version>
</dependency>

上代码!

package com.zhangan;

import com.zhangan.entity.User;
import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.serialize.SerializableSerializer;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * @Author: 张安
 * @Date: 2021/6/7 16:49
 * @Description:
 */

public class TestZkClient {

    private ZkClient client;

    @Before
    public void before() {
        /**
         * 参数
         * 服务器ip
         * 会话超时时间  单位 毫秒
         * 连接超时时间
         * 序列化方式
         */
        client = new ZkClient("192.168.29.133:2181", 60000 * 30,
                60000, new SerializableSerializer());

    }

    @After
    public void after() {
        client.close();
    }

    //在zk中创建节点
    @Test
    public void createNode() {
        //持久节点
        client.create("/node1", "zhangan", CreateMode.PERSISTENT);
        //持久顺序节点
        client.create("/node1/ps", "zhanganps", CreateMode.PERSISTENT_SEQUENTIAL);
        //临时节点
        client.create("/node1/e", "zhangane", CreateMode.EPHEMERAL);
        //临时顺序节点
        client.create("/node1/es", "zhanganes", CreateMode.EPHEMERAL_SEQUENTIAL);
    }

    //删除节点
    @Test
    public void delete() {
        //删除
        boolean delete = client.delete("/node1");
        //递归删除
        boolean deleteRecursive = client.deleteRecursive("/node1");
    }

    //查询当前节点下的所有子节点
    @Test
    public void query() {
        List<String> children = client.getChildren("/");
        for (String child : children) {
            System.out.println("child = " + child);
        }

    }

    //查看某一节点信息
    @Test
    public void get() {
        Object data = client.readData("/node1");
        System.out.println("data = " + data);
    }

    //查看节点状态
    @Test
    public void stat() {
        Stat stat = new Stat();
        Object data = client.readData("/node1", stat);

        System.out.println("data = " + data);
        System.out.println("stat = " + stat);
        System.out.println("stat.getDataLength() = " + stat.getDataLength());

    }

    //修改节点
    @Test
    public void update() {

        client.writeData("/node1", new User(1, "张安", new Date()));

        User data = client.readData("/node1");
        System.out.println(data);

    }

    //监听节点数据变化  永久监听  使用java代码操作才会触发
    @Test
    public void watchData() throws IOException {
        client.subscribeDataChanges("/node1", new IZkDataListener() {

            //数据变化时触发
            @Override
            public void handleDataChange(String dataPath, Object data) throws Exception {

                System.out.println("数据变化时触发->  当前节点路径" + dataPath);
                System.out.println("修改之后的数据" + data);
            }

            //数据删除时触发
            @Override
            public void handleDataDeleted(String dataPath) throws Exception {
                System.out.println("数据删除时触发->   当前节点路径" + dataPath);
            }
        });
        System.in.read();//阻塞客户端  为了测试
    }

    //监听节点目录变化
    @Test
    public void watchPath() throws IOException {
        client.subscribeChildChanges("/node1", new IZkChildListener() {
            //节点目录发生变化时  触发
            @Override
            public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
                System.out.println("父节点名称 = " + parentPath);
                for (String child : currentChilds) {
                    System.out.println("变化后各个子节点的名称 = " + child);
                }

            }
        });
        System.in.read();//阻塞客户端  为了测试
    }


}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值