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的临时节点 ...
随机推荐
- python邮件SMTP的GUI编程
写的是python中smtp的gui编程,用的163邮箱给qq邮箱发送邮件做测试,如果你发现你的发送失败,试着用以下方法解决: 1.网页登陆你的邮箱,设置中查看smtp是否开启,比如163邮箱的smt ...
- pycharm(windows)安装及其设置中文菜单
pycharm(windows)安装及其设置中文菜单 1.下载 在官网(http://www.jetbrains.com/pycharm/download/#section=windows)进行下载 ...
- RabbitMQ与AMQP协议
AMQP(Advanced Message Queuing Protocol, 高级消息队列协议)是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计 ...
- iOS的异步绘制--YYAsyncLayer源码分析
iOS的异步渲染 最近看了YYAsyncLayer在这里总结一下.YYAsyncLayer是整个YYKit异步渲染的基础.整个项目的Github地址在这里.你可以先下载了一睹为快,也可以跟着我一步一步 ...
- DevOps之网络
唠叨话 关于德语噢屁事的知识点,仅提供专业性的精华汇总,具体知识点细节,参考教程网址,如需帮助,请留言. <网络(Network)> 关于网络的网络架构和网络模型:知识与技能的层次(知道. ...
- 使用OLAMISDK实现一个语音输入数字进行24点计算的iOS程序
前言 在目前的软件应用中,输入方式还是以文字输入方式为主,但是语音输入的方式目前应用的越来越广泛.这是一个利用 Olami SDK 编写的一个24点iOS程序,是通过语音进行输入. Olami SDK ...
- IIS ApplicationPoolIdentity(配置IIS讀寫網站文件)
原创地址:http://www.cnblogs.com/jfzhu/p/4067297.html 转载请注明出处 从IIS 7.5开始,Application Pool Identity的Built- ...
- 【网络爬虫入门05】分布式文件存储数据库MongoDB的基本操作与爬虫应用
[网络爬虫入门05]分布式文件存储数据库MongoDB的基本操作与爬虫应用 广东职业技术学院 欧浩源 1.引言 网络爬虫往往需要将大量的数据存储到数据库中,常用的有MySQL.MongoDB和Red ...
- 01Vue数据双向绑定
Vue作为前端MV*架构,Vue.js (读音 /vjuː/,类似于 view) 是一套构建用户界面的渐进式框架.与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计. Vue 的核心库只关注 ...
- PHP设计模式三:原型设计模式
一.什么是原型设计模式 原型设计模式使用一种克隆技术来复制实例化的对象,新对象是通过复制原型实例创建的.原型设计模式的目的是通过使用克隆以减少 实例化对象的开销. 在原型设计模式中,Client类是不 ...
