Zookeeper的学习笔记

Zookeeper概念

Zookeeper是一个树形目录服务,简称zk。

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

Zookeeper提供主要的功能包括:配置管理,分布式锁,集群管理

Zookeeper命令操作

zk数据模型

zk中的每一个节点都被称为:ZNode,每个节点上都会保存自己的数据和节点信息。节点可以拥有子节点,同时也允许少量(1MB)数据存储在该节点之下

节点可以分为四大类:

  • PERSISTENT 持久化节点
  • EPHEMERAL 临时节点:-e
  • PERSISTENT_SEQUENTIAL持久化顺序节点:-s
  • EPHEMERAL_SEQUENTIAL临时顺序节点:-es

zk服务端命令

启动zk服务

./zkServer.sh start

zk查看zk服务状态

./zkServer.sh status

停止zk服务

./zkServer.sh stop

重启zk服务

./zkServer.sh restart

zk客户端命令

zkCli.sh连接ZooKeeper服务命令

./zkCli.sh [-server ip地址:2181] (如果是连接本机zk服务,可以省略[]中的内容)

查看zk中的节点

ls /[节点名称]

创建节点方法

create [节点类型] /父节点 [存储信息] (存储信息可以不写)

临时节点创建 -e(服务器关闭,下次连接就会删除)

顺序节点创建 -s

临时顺序节点创建 -es

查看节点存储信息的方法

get /目录

ls -s 是查询结点状态信息

设置节点数据

set /目录 存储信息

删除节点

delete /目录(只能删除空目录)

deleteall /目录(有子结点也可以删除)

在创建节点时,如果没有指定存储数据,那么默认存储的数据是当前服务器的ip地址

Curator介绍

CUrator是Zookeeper的Java客户端库,常见的Zookeeper Java API有三种:

  • 原生Java API
  • ZkClient
  • Curator

相较于原生Java API,Curator使用较为简单,其次,高版本的Curator可以向下兼容zk,但zk无法向下兼容Curator

Curator API常用操作

连接zk服务

一共有两种连接客户端的方式,一种是通过newClient(),一种是通过Builder链式编程创建客户端对象

@Test
public void test() throws Exception {//指定重试策略RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000, 10);//第一种连接zk方式/*参数1:指定需要连接的zk地址与端口,如果是集群模式,使用,分隔开参数2:会话超时时间参数3:连接超时时间参数4:重试策略*/CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.116.131:2181", 60 * 1000, 15 * 1000, retryPolicy);client.start();//第二种连接方式,可以指定namespace,其实是指定根目录(此后该客户端对象的curd操作都会在指定的根目录下进行)CuratorFramework client2 = CuratorFrameworkFactory.builder().connectString("192.168.116.131:2181").sessionTimeoutMs(60 * 1000).connectionTimeoutMs(15 * 1000).retryPolicy(retryPolicy).namespace("zmt").build();client2.start();
}

创建节点

创建节点默认创建节点类型为持久化,返回结果为路径,如果不指定节点存储类型,那么默认存储客户端的ip地址

@Test
public void testCreate() throws Exception {//如果不指定参数2,那么该节点的存储数据为客户端的ip地址String path = client.create().forPath("/app1","zhangsan".getBytes());System.out.println(path);//我们可以通过指定withMode来确定需要创建的节点类型,参数为枚举类client.create().withMode(CreateMode.EPHEMERAL).forPath("/app2");//创建多级节点,创建父结点,如果需要client.create().creatingParentsIfNeeded().forPath("/app3/p1");
}

查询节点

我们可以查询节点的存储信息,也可以查询节点的子节点信息,也可以查询节点的状态信息

@Test
public void testGet() throws Exception {//获取节点存储信息byte[] data = client.getData().forPath("/app1");System.out.println(new String(data));//获取子节点信息List<String> list = client.getChildren().forPath("/app3");System.out.println(list);//获取节点状态信息Stat status = new Stat();client.getData().storingStatIn(status).forPath("/app1");System.out.println(status);
}

修改节点

因为可能存在多个客户端连接同一个zookeeper,因此可能会出现修改节点数据时,其他节点也在修改的问题,因此为了避免出现同时修改同一个数据的情况发生,我们应该先获取数据的版本,然后修改数据时根据数据的版本是否一致再决定是否进行修改。

@Test
public void testSetForVersion() throws Exception {int version;Stat stat = new Stat();client.getData().storingStatIn(stat).forPath("/app1");version = stat.getVersion();System.out.println(version);client.setData().withVersion(version).forPath("/app1","lisi".getBytes());
}

删除节点

一般我们都要添加guaranteed()方法来避免网络问题产生的删除失败的问题

@Test
public void testDelete() throws Exception {//删除单个节点client.delete().forPath("/app1");//删除多级节点client.delete().deletingChildrenIfNeeded().forPath("/app3");//删除失败进行重试,直到删除成功//比如说网络不好,导致删除失败,可以重复进行删除client.delete().guaranteed().forPath("/app2");//删除回调client.delete().guaranteed().inBackground(new BackgroundCallback() {//执行回调方法@Overridepublic void processResult(CuratorFramework client, CuratorEvent event) throws Exception {System.out.println("节点被删除");System.out.println(event);}}).forPath("/app4");
}

Watch事件监听

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

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

zk提供了3种Watcher:

  • NodeCache:只监听一个特定结点
  • PathChildrenCache:监控一个Znode的子节点
  • TreeCache:前两个结合,监听自己和自己所有子节点

NodeCache的简单使用

@Test
public void testNodeCache() throws Exception {NodeCache nodeCache = new NodeCache(client, "/app1");nodeCache.getListenable().addListener(new NodeCacheListener() {@Overridepublic void nodeChanged() throws Exception {System.out.println("节点发生变化");//获取节点变化后的值byte[] data = nodeCache.getCurrentData().getData();System.out.println(new String(data));}});nodeCache.start();while (true){}
}

PathChildrenCache的简单使用

@Test
public void testChildrenCache() throws Exception {PathChildrenCache pathChildrenCache = new PathChildrenCache(client, "/", true);pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {@Overridepublic void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {System.out.println("节点发生变化");System.out.println(pathChildrenCacheEvent);PathChildrenCacheEvent.Type type = pathChildrenCacheEvent.getType();if (type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){//如果是update事件byte[] data = pathChildrenCacheEvent.getData().getData();System.out.println(new String(data));}}});pathChildrenCache.start();while (true) {}
}

TreeCache的简单使用

@Test
public void testTreeCache() throws Exception {TreeCache treeCache = new TreeCache(client,"/");treeCache.getListenable().addListener(new TreeCacheListener() {@Overridepublic void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {System.out.println("数据发生变化");System.out.println(treeCacheEvent);}});treeCache.start();while (true) {}
}

分布式锁

作用于多个JVM环境,保证多线程安全。

实现分布式锁的原理:当客户端要获取锁时,创建节点,使用完锁,删除该节点

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

采取临时节点是为了避免客户端在获取到锁之后处理业务时宕机,当客户端宕机之后,会话结束,临时节点会自动删除

Curator实现分布式锁API

一共有五种方案:

  • 分布式排他锁
  • 分布式可重入排他锁
  • 分布式读写锁
  • 将多个锁作为单个实体管理的容器
  • 共享信号量

一个简单的售票案例

public class Ticket12306 implements Runnable {//模拟十张票private int num = 10;//分布式可重入式锁private InterProcessMutex lock;public Ticket12306() {RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000, 2);CuratorFramework client = CuratorFrameworkFactory.builder().connectString("192.168.116.131:2181").connectionTimeoutMs(60*1000).sessionTimeoutMs(15*1000).retryPolicy(retryPolicy).build();client.start();lock = new InterProcessMutex(client, "/lock");}@Overridepublic void run() {while (true) {try {lock.acquire(3, TimeUnit.SECONDS);if (num > 0) {Thread.sleep(100);System.out.println(Thread.currentThread().getName() + "出售了一张票:" + num);num--;}} catch (Exception e) {System.out.println("我出错了??");e.printStackTrace();} finally {try {lock.release();} catch (Exception e) {e.printStackTrace();}}}}
}

测试 

public class TestTicket {@Testpublic void testTicket() throws Exception {Ticket12306 ticket = new Ticket12306();Thread t1 = new Thread(ticket, "携程");Thread t2 = new Thread(ticket, "飞猪");t1.start();t2.start();while(true){}}
}

实现分布式锁的核心代码如下

new 一个锁类型对象lock

lock.acquire()//获取锁

需要上锁的功能

lock.release();//释放锁

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

15-高并发-如何扩容

对于一个发展初期的系统来说&#xff0c;不太确定商业模型到底行不行&#xff0c;最好的办法是按照最小可行产品方法进行产品验证&#xff0c;因此&#xff0c;刚开始的功能会比较少&#xff0c;是一个大的单体应用&#xff0c;一般按照三层架构进行设计开发&#xff0c;使用单…

数字信号的理解

1 数字信号处理简介 数字信号处理 digital signal processing&#xff08;DSP&#xff09;经常与实际的数字系统相混淆。这两个术语都暗示了不同的概念。数字信号处理在本质上比实际的数字系统稍微抽象一些。数字系统是涉及的硬件、二进制代码或数字域。这两个术语之间的普遍混…

理解按需自动导入 unplugin-auto-import unplugin-vue-components

文章目录 unplugin-auto-import基础使用构建工具引入插件配置插件 import&#xff1a;配置自动导入规则使用预设自动引入第三方库自动导入 TypeScript 类型vue 预设的自动导入配置 dts&#xff1a;让编辑器环境识别 ts 类型eslintrc&#xff1a;解决 eslint 检查错误dirs&#…

使用PE信息查看工具和Dependency Walker工具排查因为库版本不对导致程序启动报错问题

目录 1、问题说明 2、问题分析思路 3、问题分析过程 3.1、使用Dependency Walker打开软件主程序&#xff0c;查看库与库的依赖关系&#xff0c;查看出问题的库 3.2、使用PE工具查看dll库的时间戳 3.3、解决办法 4、最后 VC常用功能开发汇总&#xff08;专栏文章列表&…

链表常见题型(1)

1.反转链表 1.1反转链表 如果我们想要反转链表&#xff0c;那应该有head的next指针指向空&#xff0c;其余结点的next指针反过来&#xff0c;指向它的上一个结点&#xff0c;那我们在执行该操作的时候就需要定义变量cur(current)表示我们当前遍历到的结点&#xff0c;变量pre(…

【后台报错】插入时sql报错,varchar撑爆

后台的一个报错。按照正常的需要复现&#xff0c;或者查一下日志。但是凭借多年经验和大胆猜测&#xff0c;以及对自己代码要自信 引用一下文章 目测7*15 105项。每个id有9个数字加上分隔符刚好十个。大概就是超过了定义的一千的varchar长度。直接改数据库就好了。 简单粗暴…

【金猿CIO展】乖宝宠物CIO王天刚:以数据为核心,转变业务模式

‍ 王天刚 本文由乖宝宠物CIO王天刚撰写并投递参与“数据猿年度金猿策划活动——2023大数据产业年度趋势人物榜单及奖项”评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 随着社会经济的快速发展&#xff0c;“宠物经济”悄然崛起&#xff0c;宠物在家中的角色地位有时…

c语言:计算1+2+3……+n的和|练习题

一、题目 输入一个数n&#xff0c;计算123……n的和 二、代码截图【带注释】 三、源代码【带注释】 #include int main() { int num0; printf("请输入要运算的数:"); scanf("%d",&num); sumResult(num);//相加结果函数 } //计算打印…

【智能家电】东胜物联离在线语音方案为厨电企业赋能,实现厨房智能化控制

近年来&#xff0c;我国厨电市场蓬勃发展。据行业统计数据显示&#xff0c;至今年6月&#xff0c;市场规模已达356亿元&#xff0c;同比增长8.8%。随着数字科技、物联网和人工智能的兴起&#xff0c;厨电产品正在朝着更智能、多功能化的方向迅速发展。 为此厨电厂商正在积极布…

EarMaster Pro 7 简体中文破解版 v7.2.0.42 电脑版

软件介绍 EarMaster破解版一款功能强大的专业级别多媒体音乐教育学习软件&#xff0c;EarMaster破解版提供了大量音乐相关的学习内容&#xff0c;用户在这里可以学习基础的和弦、音阶、节奏&#xff0c;也可以提升自己的音感&#xff0c;如果基础已经很扎实了&#xff0c;还可…

加拿大 ANUSPLIN 网格气候数据集

ANUSPLIN 网格气候数据集 加拿大 ANUSPLIN 网格气候数据集是使用澳大利亚国立大学样条 (ANUSPLIN) 模型生成的基于站点的插值数据集。它由加拿大农业和农业食品部生产&#xff0c;覆盖加拿大全境。该数据集提供 1950 年至 2015 年期间每日和每月时间步长的最高气温、最低气温和…

OpenFeign 万字教程详解

OpenFeign 万字教程详解 目录 一、概述 1.1.OpenFeign是什么&#xff1f;1.2.OpenFeign能干什么1.3.OpenFeign和Feign的区别1.4.FeignClient 二、OpenFeign使用 2.1.OpenFeign 常规远程调用2.2.OpenFeign 微服务使用步骤2.3.OpenFeign 超时控制2.4.OpenFeign 日志打印2.5.O…

【小黑嵌入式系统第十二课】μC/OS-III程序设计基础(二)——系统函数使用场合、时间管理、临界区管理、使用规则、互斥信号量

上一课&#xff1a; 【小黑嵌入式系统第十一课】μC/OS-III程序设计基础&#xff08;一&#xff09;——任务设计、任务管理&#xff08;创建&基本状态&内部任务&#xff09;、任务调度、系统函数 文章目录 一、系统函数使用场合1.1 时间管理1.1.1 控制任务的执行周期1…

CSS新手入门笔记整理:CSS3弹性盒模型

特点 子元素宽度之和小于父元素宽度&#xff0c;所有子元素最终的宽度就是原来定义的宽度。子元素宽度之和大于父元素宽度&#xff0c;子元素会按比例来划分宽度。在使用弹性盒子模型之前&#xff0c;必须为父元素定义“display:flex;”或“display:inline-flex;”。 弹性盒子…

一款基于.NET Core的快速开发框架、支持多种前端UI、内置代码生成器

前言 经常看到有小伙伴在技术群里问有没有什么好用且快速的开发框架推荐的&#xff0c;今天就给大家分享一款基于MIT License协议开源、免费的.NET Core快速开发框架、支持多种前端UI、内置代码生成器、一款高效开发的利器&#xff1a;WalkingTec.Mvvm框架&#xff08;简称WTM…

CyclicBarrier实战应用——实现异步多线程业务处理,异常情况回滚全部子线程

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; CyclicBarrier实战应用——实现异步多线程业务处理&#xff0c;异常情况…

Linux笔记本电脑投屏到电视,用网页浏览器就能投屏到电视!

Linux系统的电脑如果要投屏到安卓电视屏幕上&#xff0c;可以使用投屏工具AirDroid Cast的网页版和TV版一起实现。 首先&#xff0c;在Linux系统的电脑里用chrome浏览器或edge浏览器打开网址webcast.airdroid.com。这个网址就是AirDroid Cast的网页版。你可以看到中间白色框框的…

Canal使用详解

Canal介绍 Canal是阿里巴巴开发的MySQL binlog增量订阅&消费组件&#xff0c;Canal是基于MySQL二进制日志的高性能数据同步系统。在阿里巴巴集团中被广泛使用&#xff0c;以提供可靠的低延迟增量数据管道。Canal Server能够解析MySQL Binlog并订阅数据更改&#xff0c;而C…

cilium原理之ebpf尾调用与trace

背景 在深入剖析cilium原理之前&#xff0c;有两个关于epbf的基础内容需要先详细介绍一下&#xff1a; 1. ebpf尾调用 尾调用类似于程序之间的相互跳转&#xff0c;但它的功能更加强大。 2. trace 虽然之前使用trace_printk输出日志&#xff0c;但这个函数不能多用&#x…

使用StableDiffusion进行图片Inpainting原理

论文链接&#xff1a;RePaint: Inpainting using Denoising Diffusion Probabilistic Models代码链接&#xff1a;RePaint Inpainting任务是指在任意一个二进制的掩码指定的图片区域上重新生成新的内容&#xff0c;且新生成的内容需要和周围内容保持协调。当前SOTA模型用单一类…