3.Apache ZooKeeper数据模型
1. ZooKeeper自下向上的服务视图
Apache ZooKeeper是分布式应用程序的协调服务。 它旨在解决分布式应用程序中与组件协调相关的棘手问题。 它通过暴露一个简单而强大的接口来实现这一点。 应用程序可以设计在通过ZooKeeper API实现的这些接口上,以解决分布式同步,集群配置管理,组成员身份等问题。
ZooKeeper本身就是一个复制和分布式应用程序,其目的作为服务运行,类似于我们运行DNS或任何其他集中式服务的方式。 ZooKeeper服务的视图如下图所示:
从之前的图(该图从http://zookeeper.apache.org/doc/r3.4.6/zookeeperOver.html上能够找到),将看到运行ZooKeeper服务的复制服务器集,被称为ensemble。 客户可以通过连接到集合的任何成员来连接到ZooKeeper服务。 你可以发送和接收请求和响应,以及客户端和服务之间的事件通知,这些都是通过维护TCP连接并定期发送心跳来完成的。
Note
ensemble中的成员知道彼此的状态。 这意味着当前的内存中状态,事务日志以及服务状态的时间点副本通过构成整体的各个主机以持久的方式存储在本地数据存储中。 ZooKeeper是一个高度可用的服务,所以只要大部分服务器都可用,服务将始终可用。
ZooKeeper对事务进行了严格的排序,从而实现了简单可靠的高级分布式同步原语。 凭借其强大,可靠,高性能和快速的设计,该协调服务使其可用于大型复杂的分布式应用程序。
2. ZooKeeper数据模型
根据ZooKeeper wiki的定义,ZooKeeper允许分布式进程通过数据寄存器的共享分层命名空间相互协调。命名空间看起来非常类似于Unix文件系统。 数据寄存器在ZooKeeper命名中被称为znode。 可以在下面的图片中看到znodes的例子:
在这里,可以看到znode是一个标准的文件系统,层次结构很像一棵树。 需要注意的一些要点如下:
- 根节点有一个名为/zoo的子节点,它又有三个znode。
- ZooKeeper树中的每个znode都由一个路径标识,路径元素由『/』分隔。
- 这些节点被称为数据寄存器,因为它们可以存储数据。 因此,一个znode可以有子节点以及与之相关的数据。 这与文件系统可以把文件作为路径很类似。
znode中的数据通常以字节格式存储,每个znode中的最大数据大小不超过1 MB。 ZooKeeper是为协调而设计的,几乎所有形式的协调数据都比较小, 因此,对数据大小的限制是强制的。 建议实际的数据大小也要小于这个限制。
斜杠分隔的znode路径是规范的,必须是绝对路径。 相对路径和引用不被ZooKeeper识别。 znode名称可以由Unicode字符组成并且znode可以具有任何名称。 这个例外是ZooKeeper这个词是保留的。 最重要的是,使用“.” 作为一个路径组件是非法的。
与文件系统中的文件一样,znode维护一个stat结构,其中包含数据更改的版本号以及随更改相关的时间戳而更改的访问控制列表。 只要znode的数据发生变化,版本号就会增加。 ZooKeeper使用版本号以及相关的时间戳来验证它的核心内缓存。 znode版本号还允许客户端通过ZooKeeper API更新或删除特定的znode。 如果指定的版本号与znode的当前版本不匹配,则操作失败。 但是,执行znode更新或删除操作时,可以通过指定0作为版本号来覆盖。
(1) znode的类型
ZooKeeper有两种类型的znode:persistent和ephemeral。 可能已经听说过第三种类型,称为sequential的znode,这是另一种类型的限定符。 persistent和ephemeral的znode也可以是sequential的znode。 请注意,znode的类型是在创建时设置的。
(2) persistent类型的znode
顾名思义,persistent的znode在ZooKeeper的命名空间中有一个生命周期,直到它们被明确的删除。 一个znode可以通过调用delete API调用来删除。 没有必要只有创建持久化znode的客户端才能删除它。 请注意,任何ZooKeeper服务的授权客户端都可以删除一个znode。
现在使用ZooKeeper Java shell创建一个持久化的znode:
[zk: localhost(CONNECTED) 1] create /[PacktPub] "ApacheZooKeeper"
Created /[PacktPub]
[zk: localhost(CONNECTED) 2] get /[PacktPub]
"ApacheZooKeeper"
persistent的znodes对于存储需要高度可用且可由分布式应用程序的所有组件访问的数据时非常有用。 例如,应用程序可以将配置数据存储在持久的znode中。 即使创建者客户端死亡,数据以及znode也会存在。
(3) ephemeral类型的znode
相比之下,当创建客户端的会话结束时,ZooKeeper服务会删除一个ephemeral的znode。 客户端会话的结束可能由于客户端崩溃或连接的明确终止而发生断开连接。 尽管临时节点与客户端会话绑定,但它们对所有客户端均可见,具体取决于配置的访问控制列表(ACL)策略。
创建者客户端或任何其他授权客户端也可以通过使用删除API调用来显式删除ephemeral 的znode。 一旦其创建者客户端与ZooKeeper服务的会话结束,ephemeral 的znode就不复存在。 因此,在当前版本的ZooKeeper中,短暂的znodes不允许有子节点。
要使用ZooKeeper Java Shell创建一个ephemeral的znode,必须在create
命令中指定-e
标志,可以使用以下命令完成:
[zk: localhost(CONNECTED) 1] create -e /[PacktPub] "ApacheZooKeeper"
Created /[PacktPub]
现在,由于一个ephemeral的znode不允许有子节点,如果我们试图创建一个刚刚创建的子节点znode时,会被抛出一个错误,如下所示:
[zk: localhost(CONNECTED) 2] create -e /[PacktPub]/EphemeralChild "ChildOfEphemeralZnode"
Ephemerals cannot have children: /[PacktPub]/EphemeralChild
ephemeral的节点的用途可用于构建分布式应用程序,其中组件需要知道其他组件或资源的状态。 例如,分布式组成员资格服务可以通过使用ephemera 的znode来实现。 当创建者客户端会话结束时,ephemeral节点被删除的属性可用作加入或离开分布式集群的节点的模拟。 使用会员服务,任何节点都能够在任何特定的时间发现组的成员。
(4)sequential类型的znode
一个sequential的znode在ZooKeeper创建它的时候,分配一个序列号作为其名字的一部分。 一个单调递增的计数器(由父znode维护)的值被附加到znode的名称上。
计数器是一个有符号整数类型(4个字节),用来存储序号的。 它一共10位的格式,前面填充0。 例如,/path/to/znode-0000000001
。 这个命名约定对分配给它们的值对sequential的znode进行排序很有用。
Note
sequential的节点可以用于实现分布式全局队列,因为顺序号可以强制一个全局顺序。 它们也可以用来为分布式应用程序设计一个锁定服务。
由于persistent和ephemeral的znode都可以是sequential类型的znode,因此总共有四种znode模式:
- persistent
- ephemeral
- persistent_sequential
- ephemeral_sequential
使用ZooKeeper Java shell创建一个sequential的znode,我们必须使用create
命令的-s
标志:
[zk: localhost(CONNECTED) 1] create -s /[PacktPub] "PersistentSequentialZnode"
Created /[PacktPub]0000000001
[zk: localhost(CONNECTED) 3] create -s -e /[PacktPub] "EphemeralSequentialZnode"
Created /[PacktPub]0000000008
(5) 关注znode变化 —— ZooKeeper 监视
对于大型分布式应用程序,ZooKeeper的设计是一种可伸缩的、健壮的集中式服务。在客户端访问此类服务时,常见的设计反模式是通过轮询或拉式(pull)模型。当在大型和复杂的分布式系统中实现时,拉模型常常会受到可伸缩性问题的影响。为了解决这个问题,ZooKeeper设计了一种机制,客户端可以从ZooKeeper服务中获取通知,而不是轮询事件。这类似于一个推(push)模型,在这个模型中,通知被推送到ZooKeeper服务的注册客户端。
客户可以使用ZooKeeper服务注册与znode相关的任何更改。 这种注册被称为在ZooKeeper术语中的znode上设置监视(watch)。 监视允许客户以任何方式更改znode时收到通知。 监视是一次性操作,这意味着它只触发一个通知。 要继续接收通知,客户必须在收到每个事件通知后重新注册一个监视。
让我们通过一个集群组成员模型的例子来说明ZooKeeper监视和通知的概念:
- 在群集中,一个节点(例如Client1)在另一个节点加入群集时收到通知。 任何加入群集的节点都会在ZooKeeper路径
/Members
下创建一个ephemeral节点。 - 现在,另一个节点Client2加入群集,并在
/Members
下创建一个名为Host2的ephemeral节点。 - Client1在ZooKeeper路径
/Members
上发出一个getChildren
请求,并设置一个任何改动的监视。 当Client2创建一个znode作为/Members/Host2
时,监视被触发,Client1收到来自ZooKeeper服务的通知。 如果Client1现在在ZooKeeper路径/Members
上发出getChildren
请求,它将看到新的Host2的znode。 以下图片显示了监视设置的流程,以及监视的通知和后续重置:
ZooKeeper监视是一次性触发器。 这意味着如果一个客户端收到一个监视事件并想要得到未来变化的通知,那么它必须设置另一个监视。 每当监视被触发时,就会将一个通知分派给已经设置监视的客户端。 监视在维护与客户端连接的ZooKeeper服务器上,这使得它成为事件通知的快速和精益的方式。
监视触发以下三个变化到一个znode:
- 对znode数据的任何更改,例如使用
setData
操作将新数据写入znode的数据字段时。 - 对znode的子节点的任何更改。 例如,一个znode的子节点被删除。
- 正在创建或删除的znode,如果将新的znode添加到路径中或现有的znode被删除,则可能发生这种情况。
同样,ZooKeeper针对监视和通知声明以下保证:
- ZooKeeper确保监视始终以先进先出(FIFO)方式排序,并且通知总是按顺序发送
- 在对同一个znode进行任何其他更改之前,监视会将通知发送给客户端
- 监视事件的顺序是按照ZooKeeper服务的更新顺序排列的。
Note
由于ZooKeeper的监视是一次性触发的,由于在获取监视事件和重新设置监视之间存在延迟,所以客户端可能会在此期间丢失对znode的更改。在分布式应用程序中,一个znode在事件的调度和对事件的重新设置之间进行多次更改,开发人员必须小心处理应用程序逻辑中的这种情况。
当客户端与ZooKeeper服务器断开连接时,在连接重新建立之前,它不会收到任何监视。 如果客户重新连接,任何以前注册的监视也将被重新注册并触发。 如果客户端连接到一个新的服务器,监视将会触发任何会话事件。 从服务器断开连接并重新连接到新服务器对于客户端应用程序而言是透明的。
虽然ZooKeeper保证所有已注册的监视都被分派到客户端,但即使客户端从一台服务器断开连接并重新连接到ZooKeeper服务中的另一台服务器,也有一种可能的情况值得一提,即客户可能会错过一个监视。 这个特定的场景是,当客户端已经设置了一个尚未创建的znode的存在。 在这种情况下,在客户端处于断开状态创建和删除znode时,监视就会丢失。
3.Apache ZooKeeper数据模型的更多相关文章
- 如果你还不知道Apache Zookeeper?你凭什么拿大厂Offer!!
很多同学或多或少都用到了Zookeeper,并知道它能实现两个功能 配置中心,实现表分片规则的统一配置管理 注册中心,实现sharding-proxy节点的服务地址注册 那么Zookeeper到底是什 ...
- Apache ZooKeeper原理剖析及分布式理论名企高频面试v3.7.0
概述 **本人博客网站 **IT小神 www.itxiaoshen.com 定义 Apache ZooKeeper官网 https://zookeeper.apache.org/ 最新版本3.7.0 ...
- 微服务架构 | 3.3 Apache Zookeeper 注册中心
@ 目录 前言 1. Zookeeper 基础知识 1.1 Zookeeper 是什么 1.2 Zookeeper 的数据结构 1.3 Watcher 机制 1.4 常见应用场景分析 1.5 Zook ...
- Zookeeper数据模型及其应用
Zookeeper作为分布式系统的底层协调服务有着其简单可依靠的数据模型,数据模型加之数据同步.一致性处理和可靠性,在此之上有很多经典的应用,例如,分布式锁.服务器动态上线下感知.主节点选举.数据发布 ...
- Dubbo消费端错误: ClassNotFoundException: org.apache.zookeeper.proto.WatcherEvent
出现错误的原因是消费端war没有启动成功, 但是zkClient和Dubbo的对应Thread启动了, web container无法加载对应的类, INFO: Initializing Protoc ...
- 决战大数据之三-Apache ZooKeeper Standalone及复制模式安装及测试
决战大数据之三-Apache ZooKeeper Standalone及复制模式安装及测试 [TOC] Apache ZooKeeper 单机模式安装 创建hadoop用户&赋予sudo权限, ...
- 【Apache ZooKeeper】为ZNode设置watcher
众所周知,ZooKeeper中的ZNode是树形结构,现在我需要给/app1结点设置watcher,监听/app1下增减.删除和修改的结点,并将相应的事件使用log4j记录到日志文件中.ZNode的变 ...
- alimama open source mdrill启动后访问蓝鲸任务时出错:Caused by:org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss
启动后,访问:http://IP:1107/mdrill.jsp 蓝鲸任务
- ZooKeeper - Perl bindings for Apache ZooKeeper Perl绑定用于 Apache ZooKeeper
ZooKeeper - Perl bindings for Apache ZooKeeper Perl绑定用于 Apache ZooKeeper 监控 master/slave 需要使用zk的临时节点 ...
随机推荐
- poj1014二进制优化多重背包
Dividing Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 53029 Accepted: 13506 Descri ...
- php中常用的字符串截取函数mb_substr实例解释
string mb_substr ( string $str , int $start [, int $length = NULL [, string $encoding = mb_internal_ ...
- JAVAWEB复习资料-01
CSS中@import和link两种插入样式表方式有什么不同? 1.link属于HTML标签,除了引入css文件之外还能定义RSS等,而@import只能用于加载CSS. 2.link在引用CSS时, ...
- 我的第一个python web开发框架(5)——开发前准备工作(了解编码前需要知道的一些常识)
中午吃饭时间到了,小白赶紧向老菜坐的位置走过去. 小白:老大,中午请你吃饭. 老菜:哈哈...又遇到问题了吧,这次得狠狠宰你一顿才行. 小白:行行行,只要您赏脸,米饭任吃,嘻嘻,我们边走边聊. ... ...
- MyBatis 配置的一些小知识点
MyBatis别名配置——typeAliases 类型别名是为 Java 类型设置一个短的名字.它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余.说白了就是预先设置包名 api是这 ...
- 聊聊Java中几种常用的设计模式
1.单例模式(有的书上说叫单态模式其实都一样) 该模式主要目的是使内存中保持1个对象.看下面的例子: package org.sp.singleton; //方法一 public class Sing ...
- IDL 存储数组
IDL中的数组在内存中是按行存储的,这是因为IDL最初设计的设计目的是用来处理行扫描卫星数据. 1.一维数组 m个元素的一维数组arr[m]的存储方式为 arr[0]→arr[1]→...→arr[m ...
- 解决Jqyery的Trigger事件中两个按钮相互触发至死循环问题
今天做项目,其中有个功能需要两个图表的联动,用到两个按钮,这两个按钮分别控制两个图表,第一次直接在btn1的单击事件中使用了$("btn2").trigger("clic ...
- jquery系列教程1-选择器全解
全栈工程师开发手册 (作者:栾鹏) 快捷链接: jquery系列教程1-选择器全解 jquery系列教程2-style样式操作全解 jquery系列教程3-DOM操作全解 jquery系列教程4-事件 ...
- PHP 注释 数据类型 变量的定义/输出 类型的获取/转换 可变变量
注释方法: 1,单行注释: // 2, 多行注释: /* */ 二,数据类型 1,integer(整数型):在三十二位操作系统中它的有效范围是:-2147483648~+2147 ...