Zookeeper经典应用场景实战(一)

1. Zookeeper Java客户端实战
ZooKeeper应用的开发主要通过Java客户端API去连接和操作ZooKeeper集群。 可供选择的Java客户端API有:
· ZooKeeper官方的Java客户端API。
· 第三方的Java客户端API,比如Curator。
ZooKeeper官方的客户端API提供了基本的操作。例如,创建会话、创建节点、读取节点、更新数据、删除节点和检查节点是否存在等。不过,对于实际开发来说,ZooKeeper官方API有一些不足之处,具体如下:
· ZooKeeper的Watcher监测是一次性的,每次触发之后都需要重新进行注册。
· 会话超时之后没有实现重连机制。
· 异常处理烦琐,ZooKeeper提供了很多异常,对于开发人员来说可能根本不知道应该如何处理这些抛出的异常。
· 仅提供了简单的byte[]数组类型的接口,没有提供Java POJO级别的序列化数据处理接口。
· 创建节点时如果抛出异常,需要自行检查节点是否存在。
· 无法实现级联删除。
总之, ZooKeeper官方API功能比较简单,在实际开发过程中比较笨重,一般不推荐使用。
1.1 Zookeeper 原生Java客户端使用
引入zookeeper client依赖
注意:保持与服务端版本一致,不然会有很多兼容性的问题
ZooKeeper原生客户端主要使用org.apache.zookeeper.ZooKeeper这个类来使用ZooKeeper服务。
ZooKeeper常用构造器
· connectString:使用逗号分隔的列表,每个ZooKeeper节点是一个host.port对,host 是机器名或者IP地址,port是ZooKeeper节点对客户端提供服务的端口号。客户端会任意选取connectString 中的一个节点建立连接。
· sessionTimeout : session timeout时间。
· watcher:用于接收到来自ZooKeeper集群的事件。
使用 zookeeper 原生 API,连接zookeeper集群
Zookeeper主要方法
· create(path, data, acl,createMode): 创建一个给定路径的 znode,并在 znode 保存 data[]的数据,createMode指定 znode 的类型。
· delete(path, version):如果给定 path 上的 znode 的版本和给定的 version 匹配, 删除 znode。
· exists(path, watch):判断给定 path 上的 znode 是否存在,并在 znode 设置一个 watch。
· getData(path, watch):返回给定 path 上的 znode 数据,并在 znode 设置一个 watch。
· setData(path, data, version):如果给定 path 上的 znode 的版本和给定的 version 匹配,设置 znode数据。
· getChildren(path, watch):返回给定 path 上的 znode 的孩子 znode 名字,并在 znode 设置一个 watch。
· sync(path):把客户端 session 连接节点和 leader 节点进行同步。
方法特点:
· 所有获取 znode 数据的 API 都可以设置一个 watch 用来监控 znode 的变化。
· 所有更新 znode 数据的 API 都有两个版本: 无条件更新版本和条件更新版本。 如果 version 为 -1,更新为无条件更新。否则只有给定的 version 和 znode 当前的 version 一样,才会进行更新,这样的更新是条件更新。
· 所有的方法都有同步和异步两个版本。 同步版本的方法发送请求给 ZooKeeper 并等待服务器的响 应。异步版本把请求放入客户端的请求队列,然后马上返回。异步版本通过 callback 来接受来 自服务端的响应。
同步创建节点:
异步创建节点:
修改节点数据
1.2 Curator开源客户端使用
Curator是Netflix公司开源的一套ZooKeeper客户端框架,和ZkClient一样它解决了非常底层的细节
开发工作,包括连接、重连、反复注册Watcher的问题以及NodeExistsException异常等。
Curator是Apache基金会的顶级项目之一,Curator具有更加完善的文档,另外还提供了一套易用性和可读性更强的Fluent风格的客户端API框架。
Curator还为ZooKeeper客户端框架提供了一些比较普遍的、开箱即用的、分布式开发用的解决方案,例如Recipe、共享锁服务、Master选举机制和分布式计算器等,帮助开发者避免了“重复造轮子”的无效开发工作。
在实际的开发场景中,使用Curator客户端就足以应付日常的ZooKeeper集群操作的需求。
引入依赖
Curator 包含了几个包:
· curator-framework是对ZooKeeper的底层API的一些封装。
· curator-client提供了一些客户端的操作,例如重试策略等。
· curator-recipes封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式计数器、分布式Barrier等。
创建一个客户端实例
在使用curator-framework包操作ZooKeeper前,首先要创建一个客户端实例。这是一个CuratorFramework类型的对象,有两种方法:
· 使用工厂类CuratorFrameworkFactory的静态newClient()方法。
· 使用工厂类CuratorFrameworkFactory的静态builder构造者方法。
· connectionString:服务器地址列表 ,在指定服务器地址列表的时候可以是一个地址,也可以是多个地址。如果是多个地址,那么每个服务器地址列表用逗号分隔, 如host1:port1,host2:port2,host3;port3 。
· retryPolicy:重试策略 ,当客户端异常退出或者与服务端失去连接的时候,可以通过设置客户端重新连接ZooKeeper 服务端。而 Curator 提供了 一次重试、多次重试等不同种类的实现方式。在 Curator 内部,可以通过判断服务器返回的 keeperException 的状态代码来判断是否进行重试处理,如果返回的是 OK 表示一切操作都没有问题,而 SYSTEMERROR 表示系统或服务端错误。
· 超时时间:Curator 客户端创建过程中,有两个超时时间的设置。一个是 sessionTimeoutMs 会话超时时间 ,用来设置该条会话在 ZooKeeper 服务端的失效时间。另一个是 connectionTimeoutMs 客户端创建会话的超时时间 ,用来限制客户端发起一个会话连接到接收 ZooKeeper 服务端应答的时间。sessionTimeoutMs 作用在服务端,而 connectionTimeoutMs 作用在客户端。
创建节点
创建节点的方式如下面的代码所示,回顾我们之前课程中讲到的内容,描述一个节点要包括节点的类型,即临时节点还是持久节点、节点的数据信息、节点是否是有序节点等属性和性质。
在 Curator 中,可以使用 create 函数创建数据节点,并通过 withMode 函数指定节点类型(持久化
节点,临时节点,顺序节点,临时顺序节点,持久化顺序节点等),默认是持久化节点,之后调用
forPath 函数来指定节点的路径和数据信息。
创建节点
一次性创建带层级结构的节点
获取数据
更新节点
我们通过客户端实例的 setData() 方法更新 ZooKeeper 服务上的数据节点,在setData 方法的后边,通过 forPath 函数来指定更新的数据节点路径以及要更新的数据。
删除节点
guaranteed:该函数的功能如字面意思一样,主要起到一个保障删除成功的作用,其底层工作方式
是:只要该客户端的会话有效,就会在后台持续发起删除请求,直到该数据节点在 ZooKeeper 服务端被删除。
deletingChildrenIfNeeded:指定了该函数后,系统在删除该数据节点的时候会以递归的方式直接删除其子节点,以及子节点的子节点。
异步接口
Curator 引入了BackgroundCallback 接口,用来处理服务器端返回来的信息,这个处理过程是在异
步线程中调用,默认在 EventThread 中调用,也可以自定义线程池。
如上接口,主要参数为 client 客户端, 和服务端事件 event。
inBackground 异步处理默认在EventThread中执行
指定线程池
Curator 监听器
针对 background 通知和错误通知。使用此监听器之后,调用inBackground 方法会异步获得监听
Curator Caches:
Curator 引入了 Cache 来实现对 Zookeeper 服务端事件监听,Cache 事件监听可以理解为一个本地缓存视图与远程 Zookeeper 视图的对比过程。 Cache 提供了反复注册的功能。 Cache 分为两类注册类型:节点监听和子节点监听。
node cache:
NodeCache 对某一个节点进行监听
可以通过注册监听器来实现,对当前节点数据变化的处理
path cache:
PathChildrenCache 会对子节点进行监听,但是不会对二级子节点进行监听,
可以通过注册监听器来实现,对当前节点的子节点数据变化的处理
tree cache:
TreeCache 使用一个内部类TreeNode来维护这个一个树结构。并将这个树结构与ZK节点进行了映
射。所以TreeCache 可以监听当前节点下所有节点的事件。
可以通过注册监听器来实现,对当前节点的子节点,及递归子节点数据变化的处理
2. Zookeeper在分布式命名服务中的实战
命名服务是为系统中的资源提供标识能力。 ZooKeeper的命名服务主要是利用ZooKeeper节点的树形分层结构和子节点的顺序维护能力,来为分布式系统中的资源命名。
哪些应用场景需要用到分布式命名服务呢?典型的有:
· 分布式API目录
· 分布式节点命名
· 分布式ID生成器
2.1 分布式API目录
为分布式系统中各种API接口服务的名称、链接地址,提供类似JNDI(Java命名和目录接口)中的文件系统的功能。借助于ZooKeeper的树形分层结构就能提供分布式的API调用功能。
著名的Dubbo分布式框架就是应用了ZooKeeper的分布式的JNDI功能。在Dubbo中,使用
ZooKeeper维护的全局服务接口API的地址列表。大致的思路为:
· 服务提供者(Service Provider)在启动的时候,向ZooKeeper上的指定节
点/dubbo/${serviceName}/providers写入自己的API地址,这个操作就相当于服务的公开。
· 服务消费者(Consumer)启动的时候,订阅节点/dubbo/{serviceName}/providers下的服务提供者的URL地址,获得所有服务提供者的API。
2.2 分布式节点的命名
一个分布式系统通常会由很多的节点组成,节点的数量不是固定的,而是不断动态变化的。比如说,当业务不断膨胀和流量洪峰到来时,大量的节点可能会动态加入到集群中。而一旦流量洪峰过去了,就需要下线大量的节点。再比如说,由于机器或者网络的原因,一些节点会主动离开集群。
如何为大量的动态节点命名呢? 一种简单的办法是可以通过配置文件,手动为每一个节点命名。但
是,如果节点数据量太大,或者说变动频繁,手动命名则是不现实的,这就需要用到分布式节点的命名服务。
可用于生成集群节点的编号的方案:
(1)使用数据库的自增ID特性,用数据表存储机器的MAC地址或者IP来维护。
(2)使用ZooKeeper持久顺序节点的顺序特性来维护节点的NodeId编号。
在第2种方案中,集群节点命名服务的基本流程是:
·  启动节点服务,连接ZooKeeper,检查命名服务根节点是否存在,如果不存在,就创建系统的根节点。
· 在根节点下创建一个临时顺序ZNode节点,取回ZNode的编号把它作为分布式系统中节点的NODEID。
· [[如果临时节点太多,可以根据需要删除临时顺序ZNode节点。
2.3 分布式的ID生成器
在分布式系统中,分布式ID生成器的使用场景非常之多:
· 大量的数据记录,需要分布式ID。
· 大量的系统消息,需要分布式ID。
· 大量的请求日志,如restful的操作记录,需要唯一标识,以便进行后续的用户行为分析和调用链路分析。
· 分布式节点的命名服务,往往也需要分布式ID。
· 。。。
传统的数据库自增主键已经不能满足需求。在分布式系统环境中,迫切需要一种全新的唯一ID系统,这种系统需要满足以下需求:
(1)全局唯一:不能出现重复ID。
(2)高可用:ID生成系统是基础系统,被许多关键系统调用,一旦宕机,就会造成严重影响。
有哪些分布式的ID生成器方案呢? 大致如下:
1. Java的UUID。
2. 分布式缓存Redis生成ID:利用Redis的原子操作INCR和INCRBY,生成全局唯一的ID。
3. Twitter的SnowFlake算法。
4. ZooKeeper生成ID:利用ZooKeeper的顺序节点,生成全局唯一的ID。
5. MongoDb的ObjectId:MongoDB是一个分布式的非结构化NoSQL数据库,每插入一条记录会自动生成全局唯一的一个“_id”字段值,它是一个12字节的字符串,可以作为分布式系统中全局唯一的ID。
基于Zookeeper实现分布式ID生成器
在ZooKeeper节点的四种类型中,其中有以下两种类型具备自动编号的能力
· PERSISTENT_SEQUENTIAL持久化顺序节点。
· EPHEMERAL_SEQUENTIAL临时顺序节点。
ZooKeeper的每一个节点都会为它的第一级子节点维护一份顺序编号,会记录每个子节点创建的先后顺序,这个顺序编号是分布式同步的,也是全局唯一的。
可以通过创建ZooKeeper的临时顺序节点的方法,生成全局唯一的ID
测试
测试结果
基于Zookeeper实现SnowFlakeID算法
Twitter(推特)的SnowFlake算法是一种著名的分布式服务器用户ID生成算法。SnowFlake算法所生成的ID是一个64bit的长整型数字,如图10-2所示。这个64bit被划分成四个部分,其中后面三个部分分别表示时间戳、工作机器ID、序列号。
SnowFlakeID的四个部分,具体介绍如下:
(1)第一位 占用1 bit,其值始终是0,没有实际作用。
(2)时间戳 占用41 bit,精确到毫秒,总共可以容纳约69年的时间。
(3)工作机器id占用10 bit,最多可以容纳1024个节点。
(4)序列号 占用12 bit。这个值在同一毫秒同一节点上从0开始不断累加,最多可以累加到4095。
在工作节点达到1024顶配的场景下,SnowFlake算法在同一毫秒最多可以生成的ID数量为: 1024 *
4096 =4194304,在绝大多数并发场景下都是够用的。
SnowFlake算法的优点:
· 生成ID时不依赖于数据库,完全在内存生成,高性能和高可用性。
· 容量大,每秒可生成几百万个ID。
· ID呈趋势递增,后续插入数据库的索引树时,性能较高。
SnowFlake算法的缺点:
· 依赖于系统时钟的一致性,如果某台机器的系统时钟回拨了,有可能造成ID冲突,或者ID乱序。
· 在启动之前,如果这台机器的系统时间回拨过,那么有可能出现ID重复的危险。
基于zookeeper实现雪花算法:
3. zookeeper实现分布式队列
常见的消息队列有:RabbitMQ,RocketMQ,Kafka等。Zookeeper作为一个分布式的小文件管理系
统,同样能实现简单的队列功能。 Zookeeper不适合大数据量存储,官方并不推荐作为队列使用,但由于实现简单,集群搭建较为便利,因此在一些吞吐量不高的小型系统中还是比较好用的。
3.1 设计思路
1. 创建队列根节点:在Zookeeper中创建一个持久节点,用作队列的根节点。所有队列元素的节点将放在这个根节点下。
2. 实现入队操作:当需要将一个元素添加到队列时,可以在队列的根节点下创建一个临时有序节点。节点的数据可以包含队列元素的信息。
3. 实现出队操作:当需要从队列中取出一个元素时,可以执行以下操作: 获取根节点下的所有子节点。
。找到具有最小序号的子节点。
。获取该节点的数据。
。删除该节点。
。返回节点的数据。
3.2 使用Apache Curator实现分布式队列
Apache Curator是一个ZooKeeper客户端的封装库,提供了许多高级功能,包括分布式队列。
3.3 注意事项
使用Curator的DistributedQueue时,默认情况下不使用锁。当调用QueueBuilder的lockPath()方法
并指定一个锁节点路径时,才会启用锁。如果不指定锁节点路径,那么队列操作可能会受到并发问题的影响。
在创建分布式队列时,指定一个锁节点路径可以帮助确保队列操作的原子性和顺序性。 分布式环境
中,多个消费者可能同时尝试消费队列中的消息。如果不使用锁来同步这些操作,可能会导致消息被多次处理或者处理顺序出现混乱。当然,并非所有场景都需要指定锁节点路径。如果您的应用场景允许消息被多次处理,或者处理顺序不是关键问题,那么可以不使用锁。这样可以提高队列操作的性能,因为不再需要等待获取锁。

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

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

相关文章

【数据结构】归并排序 的递归实现与非递归实现

归并排序 前言一、归并排序递归实现(1)归并排序的核心思路归并排序运行图例(2)归并排序实现的核心步骤(3)归并排序码源详解(4)归并排序效率分析1)时间复杂度 O&#xff0…

Leetcode-234 回文链表

我的解法:使用栈,定义了len略微复杂,拿链表的后半部分和前半部分比较即可,没必要全部比较 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* List…

[极客大挑战 2019]Http 1

题目环境: 看起来挺花里胡哨的 F12查看源代码寻找隐藏文件 这是啥子呀,果然防不胜防 点击隐藏文件Secret.php 它不是来自这个地址的请求 报头:https://Sycsecret.buuoj.cn 需要抓包,在抓包前了解部分数据包参数 GET:到 Host:来自 …

ElasticSearch离线安装

1. 上传和解压软件 将elasticsearch-7.11.2-linux-x86_64.tar.gz和kibana-7.11.2-linux-x86_64.tar.gz 上传到/data/es目录 解压文件 tar -zxvf elasticsearch-7.11.2-linux-x86_64.tar.gz tar -zxvf kibana-7.11.2-linux-x86_64.tar.gz 2. 创建es用户 因为安全问题&#xff…

手机玻璃盖板为什么需要透光率检测

手机盖板,也称为手机壳或保护套,是一种用于保护手机外观和延长使用寿命的装置。它们通常由塑料、硅胶、玻璃或金属等材料制成,并固定在手机外壳上,其中任何一个工序出现差错,都有可能导致手机盖板产生缺陷,例如漏油、透…

编程中的零代码和低代码解决方案对比

目录 一、传统开发vs低代码vs零代码 (1)传统开发: (2)低代码开发: (3)零代码开发 二、5种常见的应用场景 三、零代码和低代码 随着企业数字化拉开序幕,低代码( Low Code …

【数据结构】树与二叉树(五):二叉树的顺序存储(初始化,插入结点,获取父节点、左右子节点等)

文章目录 5.1 树的基本概念5.1.1 树的定义5.1.2 森林的定义5.1.3 树的术语5.1.4 树的表示 5.2 二叉树5.2.1 二叉树1. 定义2. 特点3. 性质引理5.1:二叉树中层数为i的结点至多有 2 i 2^i 2i个,其中 i ≥ 0 i \geq 0 i≥0。引理5.2:高度为k的二叉…

10-27 maven概念

maven maven的概念模型: 项目对象模型(POM: Project object Model),一组标准集合: pom.xml 依赖管理系统(Dependency Management System) 项目生命周期(Project Lifecycle) 项目对象模型: 把项目当成一个对象,描述这个项目,使用p…

【springboot配置项动态刷新】与【yaml文件转换为java对象】

文章目录 一,序言二,准备工作1. pom.xml引入组件2. 配置文件示例 三,自定义配置项动态刷新编码实现1. 定义自定义配置项对象2. 添加注解实现启动时自动注入3. 实现yml文件监听以及文件变化处理 四,yaml文件转换为java对象1. 无法使…

机器学习——逻辑回归

一、分类问题 监督学习的最主要类型 分类(Classification): 身高1.85m,体重100kg的男人穿什么尺码的T恤?根据肿瘤的体积、患者的年龄来判断良性或恶性?根据用户的年龄、职业、存款数量来判断信用卡是否会…

Mac VsCode g++编译报错:不支持C++11语法解决

编译运行时报错: [Running] cd “/Users/yiran/Documents/vs_projects/c/” && g 1116.cpp -o 1116 && "/Users/yiran/Documents/vs_projects/c/"1116 1116.cpp:28:22: warning: range-based for loop is a C11 extension [-Wc11-extensi…

浅谈前端自定义VectorGrid矢量瓦片样式

目录 前言 一、VectorGrid相关API介绍 1、VectorGrid 2、 LayerStyles样式详解 二、样式自动配置 1、页面定义 2、地图及PBF瓦片引入 3、矢量瓦片样式定义 4、鼠标事件交互 三、最终效果 1、自定义样式展示 2、鼠标交互 总结 前言 在上一篇博客中,详细讲…

支付卡行业(PCI)PIN安全要求和测试程序 7个控制目标、33个要求及规范性附录ABC 密钥注入-PCI认证-安全行业基础篇4

概述 用于在ATM和POS终端进行在线和离线支付卡交易处理期间,对个人身份号码(PIN)数据进行安全管理、处理和传输。 该标准具体包括 7 个控制目标和 33 个安全要求, 标准的结构分为标准主体部分,标准附录(N…

FPGA高端项目:图像缩放+GTP+UDP架构,高速接口以太网视频传输,提供2套工程源码加QT上位机源码和技术支持

目录 1、前言免责声明本项目特点 2、相关方案推荐我这里已有的 GT 高速接口解决方案我这里已有的以太网方案我这里已有的图像处理方案 3、设计思路框架设计框图视频源选择ADV7611 解码芯片配置及采集动态彩条跨时钟FIFO图像缩放模块详解设计框图代码框图2种插值算法的整合与选择…

C语言:深入浅出qsort方法,编写自己的qsort完成冒泡排序

目录 什么是qsort? 函数原型 比较函数 compar 排序整型数组 排序结构体数组 根据成员字符排序 strcmp函数 根据成员整型排序 自定义qsort实现冒泡排序 qsort的实现原理 具体步骤 快速排序示例代码: 什么是qsort? qsort是 C …

YOLO目标检测——交通标志分类数据集【含对应voc、coco和yolo三种格式标签】

实际项目应用:交通标志识别数据集在自动驾驶、交通安全监控、智能交通系统、驾驶员辅助系统和城市规划等领域都有广泛应用的潜力数据集说明:交通标志分类数据集,真实场景的高质量图片数据,数据场景丰富,含多场景白天黑…

OOM排查

OOM排查 一,原因 1.一次性申请对象太多,创建了大量对象,尤其从表中读取了大量数据,循环中大量创建对象,放入list中。方案:限量 2.内存资源耗尽为释放,如connction,线程。方案&#…

猫罐头什么牌子好?2023营养又美味的猫主食罐头推荐!

亲爱的猫咪主人,你是否为你家小猫咪的挑食问题感到困扰?作为一位在宠物店工作了七年,负责喂养三十多只猫咪的店长,我对许多品牌的猫罐头都非常熟悉了。对于猫罐头哪个牌子好这个问题,我想借此机会分享一些见解。 在本…

软约束与硬约束

软约束硬约束 软约束硬约束 硬约束优化 1.基于走廊的光滑轨迹生成 2.基于贝塞尔曲线的轨迹优化 软约束优化 1.基于距离的轨迹优化 2.目标函数的设计 目标函数 光滑代价函数 碰撞代价函数 动力学代价函数。 光滑代价函数: 使用minimum snap来实现。 碰撞…

lua中的循环 while、for、repeat until三种循环方式、pairs和ipairs区别

lua中的循环 while、for、repeat until三种循环方式、pairs和ipairs区别 介绍for循环参数ipairs和pairs whilerepeat until总结 介绍 这里我用while、for、repeat until分别输出1-20之间的奇数 ,具体的语法可以看下面的代码 for循环 参数 定义一个初始值为start…
最新文章