首页 > 其他分享 >Zookeeper快速了解

Zookeeper快速了解

时间:2024-02-04 15:36:43浏览次数:26  
标签:Zookeeper ZooKeeper 了解 client println forPath 快速 节点 out

初识 Zookeeper

  • Zookeeper 是 Apache Hadoop 项目下的一个子项目,是一个树形目录服务。

  • Zookeeper 翻译过来就是动物园管理员,他是用来管 Hadoop(大象)、Hive(蜜蜂)、Pig(小猪)的管理员。简称zk

  • Zookeeper 是一个分布式的、开源的分布式应用程序的协调服务。

  • Zookeeper 提供的主要功能包括:

配置管理

分布式锁

集群管理


ZooKeeper 命令操作

Zookeeper 数据模型

  • ZooKeeper 是一个树形目录服务,其数据模型和Unix的文件系统目录树很类似,拥有一个层次化结构。

  • 这里面的每一个节点都被称为: ZNode,每个节点上都会保存自己的数据和节点信息。

  • 节点可以拥有子节点,同时也允许少量(1MB)数据存储在该节点之下。

  • 节点可以分为四大类:

    • PERSISTENT 持久化节点

    • EPHEMERAL 临时节点 :-e

    • PERSISTENT_SEQUENTIAL 持久化顺序节点 :-s

    • EPHEMERAL_SEQUENTIAL 临时顺序节点 :-es


Zookeeper 服务端常用命令

  • 启动 ZooKeeper 服务: ./zkServer.sh start
  • 查看 ZooKeeper 服务状态: ./zkServer.sh status
  • 停止 ZooKeeper 服务: ./zkServer.sh stop
  • 重启 ZooKeeper 服务: ./zkServer.sh restart

Zookeeper 客户端常用命令

连接ZooKeeper服务端:./zkCli.sh –server ip:port

断开连接:quit

查看命令帮助:help

显示指定目录下节点:ls 目录

创建节点:create /节点path value

获取节点:get /节点path

设置节点值:set /节点path value

删除单个节点:delete /节点path

删除带有子节点的节点:deleteall /节点path

创建临时节点:create -e /节点path value

创建顺序节点:create -s /节点path value

创建临时顺序节点:create -es /节点path value

查询节点详细信息: ls –s /节点path

czxid:节点被创建的事务ID

ctime: 创建时间

mzxid: 最后一次被更新的事务ID

mtime: 修改时间

pzxid:子节点列表最后一次被更新的事务ID

cversion:子节点的版本号

dataversion:数据版本号

aclversion:权限版本号

ephemeralOwner:用于临时节点,代表临时节点的事务ID,如果为持久节点则为0

dataLength:节点存储的数据的长度

numChildren:当前节点的子节点个数


ZooKeeper JavaAPI 操作

Curator 介绍

  • Curator 是 Apache ZooKeeper 的Java客户端库。
  • 常见的ZooKeeper Java API :
    • 原生Java API
    • ZkClient
    • Curator
  • Curator 项目的目标是简化 ZooKeeper 客户端的使用。
  • Curator 最初是 Netfix 研发的,后来捐献了 Apache 基金会,目前是 Apache 的顶级项目。
  • 官网:http://curator.apache.org/

Curator API 常用操作

  1. 建立连接
//创建重试的策略
ExponentialBackoffRetry retry = new ExponentialBackoffRetry(3000, 10);
/*
创建连接第一种方式
*/
CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.93.130:2181",
        60 * 1000, 15 * 1000, retry);
//开启连接
client.start();
/*
创建连接第二种方式
*/
CuratorFramework client1 = CuratorFrameworkFactory
        .builder()
        .connectString("192.168.93.130:2181")
        .sessionTimeoutMs(60 * 1000)
        .connectionTimeoutMs(15 * 10000)
        .retryPolicy(retry).namespace("jiayu").build();
//开启连接
client1.start();

  1. 添加节点
/**
* 创建节点
* 1.基本创建结点
* 2.创建节点带有数据
* 3.设置节点的类型
* 4.创建多级节点 /app1/p1
*/
//1.创建基本结点
String app1 = client.create().forPath("/app1");
System.out.println(app1);
//2.创建节点带有数据
String app2 = client.create().forPath("/app2","hehe".getBytes());
System.out.println(app2);
//3.设置节点的类型
//默认是:持久化
String app3 = client.create().withMode(CreateMode.EPHEMERAL).forPath("/app3");
System.out.println(app3);
//4.创建多级节点 /app1/p1
String app4 = client.create().creatingParentsIfNeeded().forPath("/app3/p1");
System.out.println(app4);

  1. 删除节点
/**
* 册除节点:delete deleteAll
* 1.删除单个节点: delete().forPath(/app1");
* 2.删除带有子节点的节点:delete().deletingChildrenIfNeeded().forPath("/app4");
* 3.必须成功的删除:为了防止网络抖动。本质就是重试。client.delete().guaranteed().forPath("/app2");
* 4.回调:inBackground
*/
@Test
public void testDelete() throws Exception {
    //1.删除单个节点
    client.delete().forPath("/app1");
    //2.删除带有子节点的节点
    client.delete().deletingChildrenIfNeeded().forPath("/app4");
    //3.必须成功的删除:为了防止网络抖动。本质就是重试。
    client.delete().guaranteed().forPath("/app2");
    //4.回调
    client.delete().guaranteed().inBackground(new BackgroundCallback() {
        @Override
        public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
            System.out.println("我被删除了!!!");
            System.out.println(curatorEvent);
        }
    }).forPath("/app1");
}

  1. 修改节点
/**
* 修改数据
* 1.基本修改数据:setData().forPath()
* 2.根据版本修改:setData().withVersion().forPath()
* version是通过查询出来的。目的就是为了让其他客户端或者线程不干扰我。
*/
@Test
public void testUpdate() throws Exception {
    //1.基本修改数据
    client.setData().forPath("/app1","jjjjjj".getBytes());
    //2.根据版本修改
    Stat stat = new Stat();
    client.getData().storingStatIn(stat).forPath("/app1");
    int version = stat.getVersion();
    client.setData().withVersion(version).forPath("/app1","demo".getBytes());
}

  1. 查询节点
/**
* 查询节点:
* 1.查询数据:get: getData().forPath()
* 2.查询子节点:ls: getChildren().forPath()
* 3.查询节点状态信息:ls -s:getData().storingStatIn(状态对象).forPath()
*/
@Test
public void testSelect() throws Exception {
    //1.查询数据: get
    byte[] data = client.getData().forPath("/app1");
    System.out.println(new String(data));
    //2.查询子节点: ls
    List<String> path = client.getChildren().forPath("/app4");
    System.out.println(path);
    //3.查询节点状态信息: ls -s
    Stat stat = new Stat();
    System.out.println(stat);
    System.out.println("=======================");
    client.getData().storingStatIn(stat).forPath("/app1");
    System.out.println(stat);
}

  1. Watch事件监听
  • ZooKeeper 允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,ZooKeeper 服务端会将事件通知到感兴趣的客户端上去,该机制是 ZooKeeper 实现分布式协调服务的重要特性。

  • ZooKeeper 中引入了Watcher机制来实现了发布/订阅功能能,能够让多个订阅者同时监听某一个对象,当一个对象自身状态变化时,会通知所有订阅者。

  • ZooKeeper 原生支持通过注册Watcher来进行事件监听,但是其使用并不是特别方便

  • 需要开发人员自己反复注册Watcher,比较繁琐。

  • Curator引入了 Cache 来实现对 ZooKeeper 服务端事件的监听。

  • ZooKeeper提供了三种Watcher:

    • NodeCache : 只是监听某一个特定的节点

    • PathChildrenCache : 监听某个节点的子节点们

    • TreeCache : 可以监控整个树上的所有节点,类似于PathChildrenCache和NodeCache的组合


NodeCache演示

/**
* 演示:NodeCache: 只是监听某一个特定的节点
* @throws Exception
*/
@Test
public void testNodeCache() throws Exception {
    //1.创建NodeCache对象
    final NodeCache nodeCache = new NodeCache(client, "/app1");
    //2.注册监听
    nodeCache.getListenable().addListener(new NodeCacheListener() {
        @Override
        public void nodeChanged() throws Exception {
            System.out.println("节点发生了变化!!!!!!");
            //获取操作的数据
            byte[] data = nodeCache.getCurrentData().getData();
            System.out.println(new String(data));
        }
    });
    //3.开启监听,如果设置为true,则开启监听是,加载缓冲的数据
    nodeCache.start(true);
}

PathChildrenCache演示

/**
* 演示:PathChildrenCache: 监听某个节点的子节点们
* @throws Exception
*/
@Test
public void testPathChildrenCache() throws Exception {
    //1.创建NodeCache对象
    final PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/app2",true);
    //2.注册监听
    pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
        @Override
        public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
            System.out.println("子节点发生了变化!!!!!");
            System.out.println(pathChildrenCacheEvent);
            //监听子节点的数据变更,并且拿到变更后的数据
            //1.获取类型
            PathChildrenCacheEvent.Type type = pathChildrenCacheEvent.getType();
            //判断是否是update类型
            if (type == PathChildrenCacheEvent.Type.CHILD_UPDATED){
                System.out.println("数据变了!!!!!");
                byte[] data = pathChildrenCacheEvent.getData().getData();
                System.out.println(new String(data));
            }
        }
    });
    //3.开启监听
    pathChildrenCache.start();
}

TreeCache演示

/**
* 演示:TreeCache: 可以监控整个树上的所有节点,类似于PathChildrenCache和NodeCache的组合
* @throws Exception
*/
@Test
public void testTreeCache() throws Exception {
    //1.创建NodeCache对象
    final TreeCache treeCache = new TreeCache(client, "/app2");
    //2.注册监听
    treeCache.getListenable().addListener(new TreeCacheListener() {
        @Override
        public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
            System.out.println("节点变化了!!!");
            System.out.println(treeCacheEvent);
            //获取变化后的数据
            byte[] data = treeCacheEvent.getData().getData();
            System.out.println(new String(data));
        }
    });
    //3.开启监听
    treeCache.start();
}

  1. 分布式锁实现
  • 在我们进行单机应用开发,涉及并发同步的时候,我们往往采用synchronized或者Lock的方式来解决多线程间的代码同步问题,这时多线程的运行都是在同一个JVM之下,没有任何问题。
  • 但当我们的应用是分布式集群工作的情况下,属于多JVM下的工作环境,跨JVM之间已经无法通过多线程的锁解决同步问题。
  • 那么就需要一种更加高级的锁机制,来处理种跨机器的进程之间的数据同步问题——这就是分布式锁。

分布式锁

ZooKeeper分布式锁原理

核心思想:当客户端要获取锁,则创建节点,使用完锁,则删除该节点。

  1. 客户端获取锁时,在lock节点下创建临时顺序ES节点。
  2. 然后获取lock下面的所有子节点,客户端获取到所有的子节点之后,如果发现自己创建的子节点序号最小,那么就认为该客户端获取到了锁。使用完锁后,将该节点删除。
  3. 如果发现自己创建的节点并非lock所有子节点中最小的,说明自己还没有获取到锁,此时客户端需要找到比自己小的那个节点,同时对其注册事件监听器,监听删除事件。
  4. 如果发现比自己小的那个节点被删除,则客户端的 Watcher会收到相应通知,此时再次判断自己创建的节点是否是lock子节点中序号最小的,如果是则获取到了锁,如果不是则重复以上步骤继续获取到比自己小的一个节点并注册监听。

Curator实现分布式锁API

在Curator中有五种锁方案:

  • InterProcessSemaphoreMutex:分布式排它锁(非可重入锁)
  • InterProcessMutex:分布式可重入排它锁
  • InterProcessReadWriteLock:分布式读写锁
  • InterProcessMultiLock:将多个锁作为单个实体管理的容器
  • InterProcessSemaphoreV2:共享信号量

模拟12306售票案例

public class Ticket12306 implements Runnable {
    private int tickets = 10;//数据库的票数
    private InterProcessMutex lock;
    public Ticket12306(){
        //创建重试的策略
        ExponentialBackoffRetry retry = new ExponentialBackoffRetry(3000, 10);

        CuratorFramework client = CuratorFrameworkFactory
                .builder()
                .connectString("192.168.93.130:2181")
                .sessionTimeoutMs(60 * 1000)
                .connectionTimeoutMs(15 * 10000)
                .retryPolicy(retry)
                .build();
        //开启连接
        client.start();
        lock = new InterProcessMutex(client,"/lock");
    }
    @Override
    public void run() {
        while (true) {
            try {
                lock.acquire(3, TimeUnit.SECONDS);
                if (tickets > 0) {
                    System.out.println(Thread.currentThread() + "票数:" + tickets);
                    Thread.sleep(300);
                    tickets--;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                try {
                    lock.release();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

ZooKeeper集群搭建

ZooKeeper 集群介绍

Leader选举:

  • Serverid:服务器ID:比如有三台服务器,编号分别是1,2,3。编号越大在选择算法中的权重越大。
  • Zxid:数据ID:服务器中存放的最大数据ID.值越大说明数据越新,在选举算法中数据越新权重越大。
  • 在Leader选举的过程中,如果某台ZooKeeper获得了超过半数的选票,则此ZooKeeper就可以成为Leader了。

Zookeeper 核心理论

Zookeeper 集群角色

在ZooKeeper集群服中务中有三个角色

  1. Leader 领导者 :

    • 处理事务请求

    • 集群内部各服务器的调度者

  2. Follower 跟随者 :

    • 处理客户端非事务请求,转发事务请求给Leader服务器

    • 参与Leader选举投票

  3. Observer 观察者:

    • 处理客户端非事务请求,转发事务请求给Leader服务器·

标签:Zookeeper,ZooKeeper,了解,client,println,forPath,快速,节点,out
From: https://www.cnblogs.com/uuuuZhang/p/18006321

相关文章

  • 11 - 初步了解Python
    初步了解Python参考资料:菜鸟教程:Python3基础语法PEP8:StyleGuideforPythonCodePythonDocs:SourceCodeEncoding菜鸟教程:Python3命令行参数PythonDocs:ExecutablePythonScripts知乎:#!/usr/bin/envpython有什么用?编程规范:PEP8在没有额外编程规范的前提下,建议翻阅并......
  • RabbitMQ快速入门
    MQ的基本概念MQ概述MQ全称MessageQueue(消息队列),是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信。MQ,消息队列,存储消息的中间件分布式系统通信两种方式:直接远程调用和借助第三方完成间接通信发送方称为生产者,接收方称为消费者MQ的优势和劣势优......
  • JAVA Spring Boot快速开始
    实践环境SpringBoot3.2.1Maven3.8.8JDK1.8.0_331创建项目通过http://start.spring.io/网站创建包含SpringBoot的项目,具体如下:点击GENERATE按钮后,会自动生成并下载SpringBootQuickStartDemo.zip导入项目解压述下载的项目压缩包,解压后的项目文件结构如下:E:codeProjects\Sprin......
  • 快速排序算法
    快速排序算法的核心思想是分治法(DivideandConquer)。快速排序算法通过以下步骤实现排序:1.选择基准值 :从数列中选择一个元素作为基准值(pivot),通常选择第一个元素。2.分区操作 :重新排列数列,使得所有小于基准值的元素都移到基准的前面,而所有大于基准值的元素都移到基准的后......
  • 【笔记】快速傅里叶变换
    快速傅里叶变换0记号\(\exp(x)=e^x\)。1复数(Complex)1.1三种形式代数形式:\(z=a+bi\),其中\(a,b\in\mathbbR\)。三角形式:\(z=r(\cos\theta+i\sin\theta)\),其中\(r=\sqrt{a^2+b^2}\)(\(a,b\)是在代数形式中定义的)。指数形式:\(z=r\cdote^{i\theta}\)。根据......
  • 在Unity中快速生成基于模板的Lua脚本
    在学习Xlua时,这个工具提供了一个简单而强大的方式来快速生成基于模板的Lua脚本,有助于提高开发效率和保持代码的一致性。1.xlua框架导入在GitHub上搜索xlua,找到腾讯的xlua项目,下载项目的压缩包。然后将压缩包里的Plugins和XLua这两个文件夹导入Unity的Assets目录下,如下图所示:2.......
  • 新手如何快速学习爬虫逆向?-->>爬虫之js逆向百例
    《个人练习》各位爬虫逆友如有需要请及时留言或者加vx:wzwzwz0613该案例只对学习js逆向的爬虫逆友提供技术交流,请勿进行商业交易,谢谢!技术交流群v+:......
  • 5个.NET开源且强大的快速开发框架(帮助你提高生产效率)
    中台Admin(Admin.Core)中台Admin(Admin.Core)是前后端分离权限管理系统,前端UI基于Vue3开发,后端Api基于.NET8.0开发。支持多租户、接口权限、数据权限、动态Api、任务调度、OSS文件上传、滑块拼图验证、国内外主流数据库自由切换和动态高级查询。集成统一认证授权、事件总线、......
  • 【工具】结合tcpdump/wireshark捕获码流快速构造测试场景
    源码如下:CommonHeader.h#ifndefTESTAPP_COMMONHEADER_H#defineTESTAPP_COMMONHEADER_H#include<array>#include<vector>#include<list>#include<queue>#include<stack>#include<set>#include<map>#include<......
  • 注册表监控工具可以近乎实时地监控注册表更改情况,让您不会错过任何问题。通过可自定义
    注册表监控工具可以近乎实时地监控注册表更改情况,让您不会错过任何问题。通过可自定义通知系统,您可以更轻松地及时了解用户操作或软件安装所引起的注册表更改。会在更改发生的当下显示更改(并让您进行检查和分析),而不是按特定间隔汇总活动数据,它还提供逐行精细数据,以更准确地查看注......