zookeeper学习记录

本文Java代码地址: https://gitee.com/blackjie_1/ljUp/tree/master/zookeeperDemo

个人博客网站:什么是快乐

基于docker 安装

拉取zookeeper 3.4.10

docker pull zookeeper:3.4.10

启动服务端

docker run -d -p 2181:2181 -v /root/docker/zookeeper:/home/zookeeper --name zookeeper_1 --restart always zookeeper:3.4.10

启动客户端

docker run -it --``rm` `--link zookeeper_one:zookeeper zookeeper zkCli.sh -server zookeeper

或者

docker exec -it zookeeper_1 zkCli.sh

数据模型

其数据结构类似一个树形结构,每个节点可以拥有子节点并能存储1M的数据

1、持久化

2、临时节点 -e

3、持久化顺序节点 -s

4、临时顺序节点 -es

客户端命令

连接本地zookeeper
docker exec -it zookeeper_1 zkCli.sh

或者

docker run -it --rm --link zookeeper_1:zookeeper_1 zookeeper:3.4.10  zkCli.sh -server zookeeper_1
退出
quit
查看节点
ls  /节点名称
创建节点
create /节点名称 [数据] 

create -e /节点名称 [数据]    临时节点,当前会话断开时,临时节点会删除

create -s /节点名称 [数据]    顺序节点,节点名称后会有编号
  
create -s /节点名称 [数据]    临时的顺序节点
获取数据
get /节点名称
设置数据
set /节点名称 [数据]
删除
delete  /节点名称

delete all /节点名称  删除节点及节点下所有节点

Java代码操作

maven依赖

<!-- 本次学习zookeeper版本是3.4.10-->

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-client</artifactId>
            <version>2.12.0</version>

        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.12.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.12.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

增删改查

连接
public void curatorFramework() {
        //重试策略
        ExponentialBackoffRetry exponentialBackoffRetry = new ExponentialBackoffRetry(3000, 10);

        //第一种方式
//        CuratorFramework client = CuratorFrameworkFactory
//                .newClient(zookeeperUrl, 60000, 15000, exponentialBackoffRetry);

        //第二种方法
        client = CuratorFrameworkFactory.builder()
                .connectString("192.168.106.128:2181")
                .connectionTimeoutMs(15000)
                .sessionTimeoutMs(60000)
                .retryPolicy(exponentialBackoffRetry)
                .namespace("lj")
                .build();

        client.start();
    }
新增
    /**
     * zookeeper 创建节点 持久、临时、顺序  带有数据
     * create
     * 1、创建节点并带有数据
     * 2、设置节点类型
     * 3、创建多级节点
     */
    @Test
    public void curatorCreate() throws Exception {
        //基本创建
        String app1 = client.create().forPath("/app1");
        //创建带有数据的节点
        String s1 = client.create().forPath("/app2", "李杰_app2".getBytes(StandardCharsets.UTF_8));
        //创建节点默认类型:持久化。可通过withMode方法设置类型
        String s2 = client.create().withMode(CreateMode.EPHEMERAL).forPath("/app3", "李杰_临时".getBytes(StandardCharsets.UTF_8));
        //创建多级节点
        //creatingParentsIfNeeded  :创建多级节点,如果父节点不存在则创建父节点
        String s3 = client.create().creatingParentsIfNeeded().forPath("/app4/app5", "李杰_多级节点".getBytes(StandardCharsets.UTF_8));

        System.out.println(s3);
    }
查询
 /**
     * zookeeper 查询节点
     * 1、查询字节点 ls /
     * 2、获取数据  get /
     * 3、查询节点状态 ls -s
     */
    @Test
    public void curatorQuery() throws Exception {
        //获取数据  getData
        byte[] bytes = client.getData().forPath("/app1");
        //查询子节点  getChildren
        List<String> strings = client.getChildren().forPath("/");

        //查询子节点信息+数据信息
        //stat 用于获取节点信息,结果会放在stat对象中
        Stat stat = new Stat();
        byte[] bytes1 = client.getData().storingStatIn(stat).forPath("/app2");

        System.out.println(new String(bytes1));

    }
修改
/**
     * zookeeper 修改节点数据
     * 1、修改数据
     * 2、根据版本修改数据
     */
    @Test
    public void curatorUpdate() throws Exception {
        //1、修改数据
//        client.setData().forPath("/app2","app2_修改".getBytes(StandardCharsets.UTF_8));

        //2、根据版本修改数据  withVersion
        //获取版本号
        Stat stat = new Stat();
        client.getData().storingStatIn(stat).forPath("/app2");
        //根据版本号修改数据
        client.setData()
                .withVersion(stat.getVersion())
                .forPath("/app2","app2_version_update".getBytes(StandardCharsets.UTF_8));

    }
删除
/**
     * zookeeper 删除节点
     * 1、删除单个节点
     * 2、删除带有子节点的节点
     * 3、必须成功的删除
     * 4、回调函数
     */
    @Test
    public void curatorDelete() throws Exception {
        //1、删除数据
        client.delete().forPath("/app1");

        //2、删除带有子节点的节点   deletingChildrenIfNeeded
        client.delete().deletingChildrenIfNeeded().forPath("/app4");

        //3、删除子节点 (必须删除成功,本质是重试策略) guaranteed
        client.delete().guaranteed().forPath("/app4");

        //4、回调函数 inBackground 。在删除后执行的方法
        client.delete().guaranteed().inBackground(new BackgroundCallback(){
            @Override
            public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                System.out.println("我被删除了");
                System.out.println(curatorEvent);
            }
        }).forPath("/app4");

    }

监听器

* 监听节点
* 1、监听单个节点   nodeCache
* 2、监听节点下所有子节点  PathChildrenCache
* 3、监听单个节点和节点下的所有子节点  TreeCache
监听单个节点
@Test
    public void curatorFrameworkWatch() throws Exception {
        //监听单个节点
        //1、创建监听对象
        NodeCache nodeCache = new NodeCache(client,"/app2",false);

        //2、注册监听
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                byte[] data = nodeCache.getCurrentData().getData();
                System.out.println("节点发生改变,当前值:"+new String(data));
            }
        });
        //3、开启监听
        nodeCache.start();
        while (true){

        }
    }
监听某节点下的所有子节点
/**
     * 监听某节点的所有子节点
     * @throws Exception
     */
    @Test
    public void curatorFrameworkWatchChildren() throws Exception {

        //监听某节点的所有子节点
        //1、创建监听对象PathChildrenCache
        PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/app2", true);

        //2、注册监听
        pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent event) throws Exception {
                //会监听很多数据,包括节点新增,删除,修改连接等
                System.out.println("节点发生改变");
                System.out.println(event);

                //监听子节点数据发生变化
                if(PathChildrenCacheEvent.Type.CHILD_UPDATED.equals(event.getType())){
                    // 确实是子节点数据发生变化,获取变化后的值
                    byte[] data = event.getData().getData();
                    String s = new String(data);
                    System.out.println(s);
                }
            }
        });
        //3、开启监听
        pathChildrenCache.start();
        while (true){

        }
    }
监听某节点和其所有的子节点
 /**
     * 监听某节点和其所有子节点
     * @throws Exception
     */
    @Test
    public void curatorFrameworkWatchAll() throws Exception {

        //1、创建监听对象PathChildrenCache
        TreeCache pathChildrenCache = new TreeCache(client, "/app2");

        //2、注册监听
        pathChildrenCache.getListenable().addListener(new TreeCacheListener() {
            @Override
            public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent event) throws Exception {
                //会监听很多数据,包括节点新增,删除,修改连接等
                System.out.println("节点发生改变");
                System.out.println(event);

                //监听子节点数据发生变化
                if(TreeCacheEvent.Type.NODE_UPDATED.equals(event.getType())){
                    // 确实是节点数据发生变化,获取变化后的值
                    byte[] data = event.getData().getData();
                    String s = new String(data);
                    System.out.println(s);
                }
            }
        });
        //3、开启监听
        pathChildrenCache.start();
        while (true){

        }
    }

分布式锁

简略概念:多机器下的对于锁的处理。实现方式:

1、redis (性能高,但是不是很可靠)

2、数据库实现(获得锁:数据库新增一条唯一数据。释放锁:删除新增的数据。锁等待:等新增成功。此思想同样可以用redis实现。)

3、zookeeper

在这里插入图片描述

Java代码实现

本次使用的锁是InterProcessMutex

主要步骤:

1、构建CuratorFramework client 对象

2、通过client 构建InterProcessMutex 对象:lock= new InterProcessMutex(client, “/lock”);

3、执行业务前获取锁:boolean acquire = lock.acquire(5, TimeUnit.SECONDS);

4、业务结束后释放锁:lock.release();

模拟售票

public class ZookeeperLockTests {

   private static class Tick12306{
        private int tick=100;

        public int buyTick(){
            int result=0;
            if(tick>0){
                result=tick;
                tick--;
            }else{
                System.out.println("无票了");
                return -1000;
            }
            return result;
        }
   }
   private static class OtherTick implements Runnable{
       //抢票机构名称
       private String name;

       //12306票池
       private Tick12306 tick12306;

       //分布式锁
       private InterProcessMutex lock;

       public OtherTick(String name,Tick12306 tick12306){
           this.name=name;
           this.tick12306=tick12306;
           //重试策略
           ExponentialBackoffRetry exponentialBackoffRetry = new ExponentialBackoffRetry(3000, 10);

           CuratorFramework client = CuratorFrameworkFactory.builder()
                   .connectString("192.168.106.128:2181")
                   .connectionTimeoutMs(15000)
                   .sessionTimeoutMs(60000)
                   .retryPolicy(exponentialBackoffRetry)
                   .namespace("lj")
                   .build();

           client.start();

           lock = new InterProcessMutex(client, "/lock");
       }

       //抢票
       @Override
       public void run() {

           while (tick12306.tick>0){
               try {
                   //获取锁
                   boolean acquire = lock.acquire(5, TimeUnit.SECONDS);
                   if(acquire){
                       System.out.println(this.name+"抢票:"+tick12306.buyTick());
                   }
               }catch (Exception e){
                   e.printStackTrace();
               }finally {
                   try {
                       //锁释放
                       lock.release();
                   } catch (Exception e) {
                       e.printStackTrace();
                   }
               }

           }
       }
   }


    public static void main(String[] args) {
        Tick12306 tick12306 = new Tick12306();
        OtherTick t1 = new OtherTick("携程", tick12306);
        OtherTick t2 = new OtherTick("飞猪", tick12306);
        Thread thread1 = new Thread(t1);
        Thread thread2 = new Thread(t2);
        thread1.start();
        thread2.start();
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/153988.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

现在做跨境电商还需要全球代理IP吗?全球代理IP哪家靠谱?

随着全球互联网的发展&#xff0c;电商平台的发展和跨境贸易的便利化&#xff0c;跨境电商在过去几年中也一直呈现增长趋势&#xff0c;吸引了越来越多的企业和个体创业者入行。 然而&#xff0c;行业竞争也在不断加剧&#xff0c;跨境电商面临更多的越来越多的挑战&#xff0…

c语言中,/100和/100.0的区别是什么?

c语言中&#xff0c;/100和/100.0的区别是什么&#xff1f; 应该是整数除法和浮点数除法的区别吧。/100 时&#xff0c;结果只会保留整数部分&#xff0c;余数会丢弃。 最近很多小伙伴找我&#xff0c;说想要一些c语言的资料&#xff0c;然后我根据自己从业十年经验&#xff0…

哈夫曼编码详细证明步骤

关于哈夫曼编码&#xff0c;想必大家都很清楚&#xff0c;这里来讲解一下他的详细证明方法。代码的话就不给了网上一大堆&#xff0c;我再给也没什么意思&#xff0c;这里主要讲明白正确性的证明。我将采取两种方法进行证明&#xff0c;一种常规的方法&#xff0c;还有一种采取…

完整时间线!李开复Yi大模型套壳争议;第二届AI故事大赛;AI算命GPTs;LLM应用全栈开发笔记;GPT-5提上日程 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f440; 李开复「零一万物」大模型陷套壳争议&#xff0c;事件时间线完整梳理 https://huggingface.co/01-ai/Yi-34B/discussions/11#65531458…

振南技术干货集:比萨斜塔要倒了,倾斜传感器快来!(1)

注解目录 1、倾斜传感器的那些基础干货 1.1 典型应用场景 &#xff08;危楼、边坡、古建筑都是对倾斜敏感的。&#xff09; 1.2 倾斜传感器的原理 1.2.1 滚珠式倾斜开关 1.2.2 加速度式倾斜传感器 1)直接输出倾角 2)加速度计算倾角 3)倾角精度的提高 &#xff08;如果…

Kettle工具使用小结1

1.背景 客户数据库限定为tidb数据库&#xff0c;相关业务数据均存储在内。因为tidb数据库是分布式的&#xff0c;且不支持存储过程、job等功能&#xff0c;需要通过外部工具进行脚本批量处理&#xff0c;所以这里引入kettle进行脚本批量执行和作业调度。 2.环境信息 &#xf…

SpringBoot配置数据库密码加密的方法

由于系统安全的考虑,配置文件中不能出现明文密码的问题,本文就给大家详细介绍下springboot配置数据库密码加密的方法,下面话不多说了,来一起看看详细的介绍吧,需要的朋友可以参考下 1.导入依赖 <!--数据库密码加密--> <dependency><groupId>com.github.uli…

探索arkui(2)--- 布局(列表)--- 2(支持分组/实现响应滚动位置)

前端开发布局是指前端开发人员宣布他们开发的新网站或应用程序正式上线的活动。在前端开发布局中&#xff0c;开发人员通常会展示新网站或应用程序的设计、功能和用户体验&#xff0c;并向公众宣传新产品的特点和优势。前端开发布局通常是前端开发领域的重要事件&#xff0c;吸…

Leetcode88 合并两个有序数组

合并两个有序数组 题解1 正向(记得插1删1)题解2 逆向 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减…

WEB 自动化神器 TestCafe(一)—安装和入门篇

今天小编给大家带来WEB 自动化神器 TestCafe(一) —安装和入门篇 一、TestCafe 介绍&#xff1a; TestCafe 是一款基于 Node.js 的端到端 Web 自动化测试框架&#xff0c;支持 TypeScript 或 JavaScript 来编写测试用例&#xff0c;运行用例&#xff0c;并生成自动化测试报告。…

传输层——— UDP协议

文章目录 一.传输层1.再谈端口号2.端口号范围划分3.认识知名端口号4.两个问题5.netstat与iostat6.pidof 二.UDP协议1.UDP协议格式2.UDP协议的特点3.面向数据报4.UDP的缓冲区5.UDP使用注意事项6.基于UDP的应用层协议 一.传输层 在学习HTTP等应用层协议时&#xff0c;为了便于理…

计算机网络的发展

目录 一、计算机网络发展的四个阶段 1、第一阶段&#xff1a;面向终端的计算机网络&#xff08;20世纪50年代&#xff09; 2、第二阶段&#xff1a;计算机—计算机网络&#xff08;20世纪60年代&#xff09; 3、第三阶段&#xff1a;开放式标准化网络&#xff08;20世纪70年…

vue3别名配置(vite)

1、配置别名的优点&#xff1a; 在VUE项目中import导入文件时&#xff0c;可以写相对路径. 2、在vite.config.js中配置 a. 首先引入path import path from "path"/* */ b.在resolve添加别名&#xff0c;例如&#xff1a; alias:{"~":path.resolve(__di…

jQuery【jQuery树遍历、jQuery动画(一)、jQuery动画(二)】(四)-全面详解(学习总结---从入门到深化)

目录 jQuery树遍历 jQuery动画(一) jQuery动画(二) jQuery树遍历 1、 .children() 获得子元素&#xff0c;可以传递一个选择器参数 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-…

批量处理文件夹及子文件夹下文件名

从此烟雨落京城&#xff0c;一人撑伞两人行。 问题描述 下载的资源被打过标记&#xff0c;不能直接使用&#xff0c;甚是痛苦 问题&#xff1a; 所有文件的文件名都加入了【更多it教程 微信号&#xff1a;…】字段&#xff0c;包括当前文件夹和子文件夹的全部文件&#xff0c…

leetcode:链表的中间结点

1.题目描述 题目链接&#xff1a;876. 链表的中间结点 - 力扣&#xff08;LeetCode&#xff09; 我们先看题目描述&#xff1a; 2.解题思路 我们用画图用快慢指针来解决这个问题 定义一个快指针fast&#xff0c;一个慢指针slow 快指针一次走两个结点&#xff0c;慢指针一次…

vscode终端npm install报错

报错如下&#xff1a; npm WARN read-shrinkwrap This version of npm is compatible with lockfileVersion1, but package-lock.json was generated for lockfileVersion2. Ill try to do my best with it! npm ERR! code EPERM npm ERR! syscall open npm ERR! errno -4048…

【AI视野·今日Sound 声学论文速览 第三十四期】Thu, 26 Oct 2023

AI视野今日CS.Sound 声学论文速览 Thu, 26 Oct 2023 Totally 9 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers Dynamic Processing Neural Network Architecture For Hearing Loss Compensation Authors Szymon Drgas, Lars Bramsl w, Archontis Poli…

LeetCode(21)反转字符串中的单词【数组/字符串】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 151. 反转字符串中的单词 1.题目 给你一个字符串 s &#xff0c;请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 返回 单词 顺序颠倒且 单词 之间用单…

Java实现俄罗斯方块游戏

俄罗斯方块游戏本身的逻辑&#xff1a; 俄罗斯方块游戏的逻辑是比较简单的。它就类似于堆砌房子一样&#xff0c;各种各样的方地形状是不同的。但是&#xff0c;俄罗斯方块游戏的界面被等均的分为若干行和若干列&#xff0c;因此方块的本质就是占用了多少个单元。 首先来考虑…