Zookeeper学习笔记

Zookeeper学习笔记

本文章基于B站UP主:编程不良人 视频教程《Zookeeper》进行整理记录,仅用于个人学习/交流,使用

视频教程:

参考资料:

Zookeeper概述

基本概念

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

内存模型

image-20211202193156294

模型的特点:

每个子目录如/node1都被称作一个znode(节点),这个znode是被它所在的路径唯一标识

znode可以有子节点目录,并且每个znode可以存储数据

znode是有版本的,每个 znode中存储的数据可以有多个版本,也就是一个访问路径中可以存储多份数据

znode可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端

节点的分类

持久节点(PERSISTENT)

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

持久顺序节点(PERSISTENT_SEQUENTtAL)

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

临时节点(EPHEMERAL)

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

临时顺序节点(EPHEMERAL_SEQUENTIAL)

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

安装Zookeeper

Linux安装Zookeeper

image-20211202193719229

Docker安装Zookeeper

image-20211202193741407

配置文件说明

配置文件位置:apache-zookeeper-3.7.0\conf\zoo.cfg

说明:

image-20220110203106692

image-20220110203127909

客户端基本命令

基本指令

image-20211202194256462

部分指令说明

ls2 指令= ls + stat

image-20211202194354419

stat指令详细信息

image-20211202194508592

delete指令 和 rmr指令

image-20211202194539941

节点监听机制

机制说明

客户端可以监测znode节点的变化。Zonode节点的变化触发相应的事件,然后清除对该节点的监测。当监测一个znode节点时候,Zookeeper会发送通知给监测节点。

一个Watch事件是一个一次性的触发器,当被设置了Watch的数据和目录发生了改变的时候,则服务器将这个改变发送给设置Watch的客户端以便通知它们。

1.1s /path true
监听节点目录的变化

2.get /path true
监听节点数据的变化。

使用案例

image-20211202194742049

Java操作ZK

建立连接

        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.11</version>
        </dependency>
    @Test
    public void testConnection(){
        //1. zk server 服务器 ip地址、端口号
        //2、会话超时时间
        //3、连接超时时间
        //4、序列化方式(对象序列化的方式)
        ZkClient zkClient = new ZkClient("106.55.100.58:2181", 60000 * 30, 60000, new SerializableSerializer());
        System.out.println(zkClient);

        //释放资源
        //调用close方法之后,相当于关闭连接,创建的==临时节点会消失==
        zkClient.close();
    }

API操作

    
	public static ZkClient zkClient;
    
    @BeforeAll //初始化客户端对象
    public static void Before(){
        zkClient = new ZkClient("106.55.100.58:2181", 60000 * 30, 60000, new SerializableSerializer());
    }

    @AfterAll //释放资源
    public static void After(){
        zkClient.close();
    }


    //1.创建节点
    @Test
    public void testCreateNode(){
        //1.1 持久节点
        zkClient.create("/node1","zhangsan", CreateMode.PERSISTENT);
        //1.2 持久顺序节点
        zkClient.create("/node1/name","lisi",CreateMode.PERSISTENT_SEQUENTIAL);
        //1.3 临时节点
        zkClient.create("/node2","wangwu",CreateMode.EPHEMERAL);
        //1.4 临时顺序节点
        zkClient.create("/node2/name1","zhaoliu",CreateMode.EPHEMERAL_SEQUENTIAL);
    }

    //2.删除节点
    @Test
    public void testDeleteNode(){
        //2.1 删除没有子节点的节点
        boolean delete = zkClient.delete("/node1");
        System.out.println(delete);

        //2.2 递归删除节点
        boolean b = zkClient.deleteRecursive("/node1");
        System.out.println(b);
    }

    //3.查询某个结点下的所有节点
    @Test
    public void testFindNodes(){
        List<String> children = zkClient.getChildren("/node1");
        children.forEach(System.out::println);
    }

    //4.查看某个节点的数据
    @Test
    public void testFindNodeData(){
        Object node1 = zkClient.readData("/node1");
        System.out.println(node1);
    }

    //5.查看节点的状态信息
    @Test
    public void testNodeDataAndStat(){
        Stat stat=new Stat();
        Object readData = zkClient.readData("/node1", stat);
        System.out.println(readData);
        System.out.println(stat.getCversion());
        System.out.println(stat.getCtime());
        System.out.println(stat.getCzxid());
    }


    //6.修改节点数据
    @Test
    public void testWriteData(){
        User user=new User();
        user.setId(1).setName("zhangsan").setAge(18).setBir(new Date());
        zkClient.writeData("/node1",user);

        //读测试
        User user1 = zkClient.readData("/node1");
        System.out.println(user1);
    }

Tips1:查看某个节点数据时,要保证数据序列化方式一致

image-20211203095415046

Tips2:保存自定义对象数据时,要让自定义对象实现序列化

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Accessors(chain = true)
public class User implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
    private Date bir;
}

Tips3:调用close方法之后,相当于关闭连接,创建的临时节点会消失

监听机制

Java能够实现永久监听,Shell中只能一次监听

使用Java代码监听只能监听对Java代码对节点的操作,不能监听Shell对节点的操作

使用Shell监听节点时,能够监听Java代码对节点的操作

使用代码对目录监听是永久监听,假设监听node1,即使删除node1后,在创建一个新的node1,这个node1依旧能被监听

    //7.监听节点数据变化
    @Test
    public void testWatchDataChange() throws IOException {
        zkClient.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();
    }
    //8.监听节点目录变化
    @Test
    public void testWathchPathChange() throws IOException {
        zkClient.subscribeChildChanges("/node1", new IZkChildListener() {
            //当节点发生变化时,会自动调用这个方法
            //参数1:父节点的名称
            //参数2:父节点中的所有子节点的名称
            @Override
            public void handleChildChange(String nodeName, List<String> list) throws Exception {
                System.out.println("父节点名称:" +nodeName);
                System.out.println("发生变更后子节点名称:");
                list.forEach(System.out::println);
            }
        });
        System.in.read();
    }

搭建ZK集群

推荐博客:https://my.oschina.net/longkingxu/blog/1802140

集群概述

1.集群

集合同一种软件服务的多个节点同时提供服务

2.集群解决问题

单节点的并发访问的压力问题

单节点故障问题(如硬件老化,自然灾害等)

集群架构

image-20211203103905571

zab,原子广播协议

数据一致性,高度一致:

当我们连接ZK集群中的任意一个节点之后,对他写入数据,但这个节点并不会立即写入自己的节点,而是向Leader节点进行通信,发起一次确认,当主节点确认可以写之后,做原子广播,其他节点同步的写入数据,如果某个客户端写入失败,则直接报错给客户端(所有已经写入数据的节点,撤销回滚),直至集群中的所有节点都确认这个数据之后,这个数据才会成为集群数据的一部分

following原子同步leader节点中数据

leader节点宕机之后,following节点会选举

集群搭建

image-20211203103812818

Java使用ZK集群

1.填写ZK集群中的任意一个节点的IP地址,既可以使用集群

2.填写ZK集群总所有节点的IP地址,防止(1)中当前节点宕机,但集群依旧可以的情况

image-20211203104112780

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值