ZooKeeper技术内幕

news2024/9/20 16:23:05

从系统模型、序列化与协议、客户端工作原理、会话、服务端工作原理以及数据存储等方面来向揭示ZooKeeper的技术内幕,更深入地了解ZooKeeper这一分布式协调框架。

1、系统模型

将从数据模型、节点特性、版本、Watcher和ACL五方面来讲述ZooKeeper的系统模型。

1.1、数据模型

ZooKeeper的视图结构和标准的Unix文件系统非常类似,但没有引入传统文件系统中目录和文件等相关概念,而是使用了其特有的“数据节点”概念,我们称之为ZNode。ZNode是ZooKeeper中数据的最小单元,每个ZNode上都可以保存数据,同时还可以挂载子节点,因此构成了一个层次化的命名空间,我们称之为树。


首先我们来看下图所示的ZooKeeper数据节点示意图,从而对ZooKeeper上的数据节点有一个大体上的认识。在ZooKeeper中,每一个数据节点都被称为一个ZNode,所有ZNode按层次化结构进行组织,形成一棵树。ZNode的节点路径标识方式和Unix文件系统路径非常相似,都是由一系列使用斜杠(/)进行分割的路径表示,开发人员可以向这个节点中写入数据,也可以在节点下面创建子节点。
在这里插入图片描述
事务ID
在《事务处理:概念与技术》一书中提到,事务是对物理和抽象的应用状态上的操作集合。在现在的计算机科学中,狭义上的事务通常指的是数据库事务,一般包含了一系列对数据库有序的读写操作,这些数据库事务具有所谓的ACID特性,即原子性(Atomic)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。

在ZooKeeper中,事务是指能够改变ZooKeeper服务器状态的操作,我们也称之为事务操作或更新操作,一般包括数据节点创建与删除、数据节点内容更新和客户端会话创建与失效等操作。对于每一个事务请求,ZooKeeper都会为其分配一个全局唯一的事务ID,用ZXID来表示,通常是一个64位的数字。每一个ZXID对应一次更新操作,从这些ZXID中可以间接地识别出ZooKeeper处理这些更新操作请求的全局顺序。

1.2、节点特性

ZooKeeper的命名空间是由一系列数据节点组成的,在本节中,将对数据节点做详细讲解。

1.2.1、节点类型

在ZooKeeper中,每个数据节点都是有生命周期的,其生命周期的长短取决于数据节点的节点类型。在ZooKeeper中,节点类型可以分为持久节点(PERSISTENT)、临时节点(EPHEMERAL)和顺序节点(SEQUENTIAL)三大类,具体在节点创建过程中,通过组合使用,可以生成以下四种组合型节点类型:

持久节点(PERSISTENT)
持久节点是ZooKeeper中最常见的一种节点类型。所谓持久节点,是指该数据节点被创建后,就会一直存在于ZooKeeper服务器上,直到有删除操作来主动清除这个节点。

持久顺序节点(PERSISTENT_SEQUENTIAL)
持久顺序节点的基本特性和持久节点是一致的,额外的特性表现在顺序性上。在ZooKeeper中,每个父节点都会为它的第一级子节点维护一份顺序,用于记录下每个子节点创建的先后顺序。基于这个顺序特性,在创建子节点的时候,可以设置这个标记,那么在创建节点过程中,ZooKeeper会自动为给定节点名加上一个数字后缀,作为一个新的、完整的节点名。另外需要注意的是,这个数字后缀的上限是整型的最大值。

临时节点(EPHEMERAL)
和持久节点不同的是,临时节点的生命周期和客户端的会话绑定在一起,也就是说,如果客户端会话失效,那么这个节点就会被自动清理掉。注意,这里提到的是客户端会话失效,而非TCP连接断开。另外,ZooKeeper规定了不能基于临时节点来创建子节点,即临时节点只能作为叶子节点。

临时顺序节点(EPHEMERAL_SEQUENTIAL)
临时顺序节点的基本特性和临时节点也是一致的,同样是在临时节点的基础上,添加了顺序的特性。

状态信息
可以针对ZooKeeper上的数据节点进行数据的写入和子节点的创建。事实上,每个数据节点除了存储了数据内容之外,还存储了数据节点本身的一些状态信息。

1.3、版本——保证分布式数据原子性操作

ZooKeeper中为数据节点引入了版本的概念,每个数据节点都具有三种类型的版本信息,对数据节点的任何更新操作都会引起版本号的变化,下表中对这三类版本信息分别进行了说明。
在这里插入图片描述
ZooKeeper中的版本概念和传统意义上的软件版本有很大的区别,它表示的是对数据节点的数据内容、子节点列表,或是节点ACL信息的修改次数,我们以其中的version这种版本类型为例来说明。在一个数据节点/zk-book被创建完毕之后,节点的version值是0,表示的含义是“当前节点自从创建之后,被更新过0次”。如果现在对该节点的数据内容进行更新操作,那么随后,version的值就会变成1。同时需要注意的是,在上文中提到的关于version的说明,其表示的是对数据节点数据内容的变更次数,强调的是变更次数,因此即使前后两次变更并没有使得数据内容的值发生变化,version的值依然会变更。

在上面的介绍中,我们基本了解了ZooKeeper中的版本概念。那么版本究竟用来干嘛呢?在讲解版本的作用之前,我们首先来看下分布式领域中最常见的一个概念——锁。

一个多线程应用,尤其是分布式系统,在运行过程中往往需要保证数据访问的排他性。

悲观锁,又被称作悲观并发控制(Pessimistic Concurrency Control,PCC),是数据库中一种非常典型且非常严格的并发控制策略。悲观锁具有强烈的独占和排他特性,能够有效地避免不同事务对同一数据并发更新而造成的数据一致性问题。在悲观锁的实现原理中,如果一个事务(假定事务A)正在对数据进行处理,那么在整个处理过程中,都会将数据处于锁定状态,在这期间,其他事务将无法对这个数据进行更新操作,直到事务A完成对该数据的处理,释放了对应的锁之后,其他事务才能够重新竞争来对数据进行更新操作。也就是说,对于一份独立的数据,系统只分配了一把唯一的钥匙,谁获得了这把钥匙,谁就有权力更新这份数据。一般我们认为,在实际生产应用中,悲观锁策略适合解决那些对于数据更新竞争十分激烈的场景——在这类场景中,通常采用简单粗暴的悲观锁机制来解决并发控制问题。

乐观锁,又被称作乐观并发控制(Optimistic Concurrency Control,OCC),也是一种常见的并发控制策略。相对于悲观锁而言,乐观锁机制显得更加宽松与友好。从上面对悲观锁的讲解中我们可以看到,悲观锁假定不同事务之间的处理一定会出现互相干扰,从而需要在一个事务从头到尾的过程中都对数据进行加锁处理。而乐观锁则正好相反,它假定多个事务在处理过程中不会彼此影响,因此在事务处理的绝大部分时间里不需要进行加锁处理。当然,既然有并发,就一定会存在数据更新冲突的可能。在乐观锁机制中,在更新请求提交之前,每个事务都会首先检查当前事务读取数据后,是否有其他事务对该数据进行了修改。如果其他事务有更新的话,那么正在提交的事务就需要回滚。乐观锁通常适合使用在数据并发竞争不大、事务冲突较少的应用场景中。

从上面的讲解中,我们其实可以把一个乐观锁控制的事务分成如下三个阶段:数据读取、写入校验和数据写入,其中写入校验阶段是整个乐观锁控制的关键所在。在写入校验阶段,事务会检查数据在读取阶段后是否有其他事务对数据进行过更新,以确保数据更新的一致性。那么,如何来进行写入校验呢?我们首先可以来看下JDK中最典型的乐观锁实现——CAS。简单地讲就是“对于值V,每次更新前都会比对其值是否是预期值A,只有符合预期,才会将V原子化地更新到新值B”,其中是否符合预期便是乐观锁中的“写入校验”阶段。

好了,现在我们再回过头来看看ZooKeeper中版本的作用。事实上,在ZooKeeper中,version属性正是用来实现乐观锁机制中的“写入校验”的。在ZooKeeper服务器的PrepRequestProcessor处理器类中,在处理每一个数据更新(setDataRequest)请求时,会进行如下清单所示的版本检查。
在这里插入图片描述
从上面的执行逻辑中,我们可以看出,在进行一次setDataRequest请求处理时,首先进行了版本检查:ZooKeeper会从setDataRequest请求中获取到当前请求的版本version,同时从数据记录nodeRecord中获取到当前服务器上该数据的最新版本currentVersion。如果version为“-1”,那么说明客户端并不要求使用乐观锁,可以忽略版本比对;如果version不是“-1”,那么就比对version和currentVersion,如果两个版本不匹配,那么将会抛出BadVersionException异常。

1.4、 Watcher——数据变更的通知

ZooKeeper提供了分布式数据的发布/订阅功能。一个典型的发布/订阅模型系统定义了一种一对多的订阅关系,能够让多个订阅者同时监听某一个主题对象,当这个主题对象自身状态变化时,会通知所有订阅者,使它们能够做出相应的处理。在ZooKeeper中,引入了Watcher机制来实现这种分布式的通知功能。ZooKeeper允许客户端向服务端注册一个Watcher监听,当服务端的一些指定事件触发了这个Watcher,那么就会向指定客户端发送一个事件通知来实现分布式的通知功能。整个Watcher注册与通知过程如下图所示:
在这里插入图片描述
从下图中,我们可以看到,ZooKeeper的Watcher机制主要包括客户端线程、客户端WatchManager和ZooKeeper服务器三部分。在具体工作流程上,简单地讲,客户端在向ZooKeeper服务器注册Watcher的同时,会将Watcher对象存储在客户端的WatchManager中。当ZooKeeper服务器端触发Watcher事件后,会向客户端发送通知,客户端线程从WatchManager中取出对应的Watcher对象来执行回调逻辑。

Watcher接口
在ZooKeeper中,接口类Watcher用于表示一个标准的事件处理器,其定义了事件通知相关的逻辑,包含KeeperState和EventType两个枚举类,分别代表了通知状态和事件类型,同时定义了事件的回调方法:process(WatchedEvent event)。

Watcher事件
同一个事件类型在不同的通知状态中代表的含义有所不同,下表列举了常见的通知状态和事件类型。
在这里插入图片描述

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

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

相关文章

最新Nmap进阶技术

点击星标,即时接收最新推文 本文选自《web安全攻防渗透测试实战指南(第2版)》 点击图片五折购书 Nmap进阶 1.脚本介绍 Nmap的脚本默认存在于/Nmap/scripts文件夹下,如图3-71所示。 图3-71 Nmap的脚本主要分为以下几类…

Visio 导出 PDF 文件 图片分辨率被降采样怎么解决

前言 在科研出图中,matlab 绘制图标后续使用 Visio,adobe illustrator,inkscape 相关内容可以参考这里。 此处解决在Visio中对实物图示意图进行标注后,使用Visio另存为, 打印,导出等输出的PDF文档中的图片…

Linux中的dpkg指令(dpkg -l | grep XXX等)

dpkg是Debian包管理系统中的一个工具,用于在Linux系统中安装、升级、删除和管理软件包。它是Debian、Ubuntu以及基于它们的发行版中的包管理器。 dpkg 有很多用法,常用之举例:dpkg -l | grep apt 显示系统中安装的与apt相关(命名&#xff09…

MATLAB 2023安装方法之删除旧版本MATLAB,安装新版本MATLAB

说明:之前一直使用的是MATLAB R2020b,但最近复现Github上的程序时,运行不了,联系作者说他的程序只能在MATLAB 2021之后的版本运行,因此决定安装最新版本的MATLAB。 系统:Windows 11 需要卸载的旧MATLAB 版…

DDD中聚合、聚合根的含义以及作用

聚合与聚合根的含义 聚合: 聚合往往是一些实体为了某项业务而聚类在一起形成的集合 , 举个例子, 社会是由一个个的个体组成的,象征着我们每一个人。随着社会的发展,慢慢出现了社团、机构、部门等组织,我们开始从个人变…

计网第四章(网络层)(七)

一、路由信息协议RIP 路由信息协议RIP是互联网中最早使用的协议,他是基于距离向量的。 1.距离向量: RIP要求自治系统AS内的每一个路由器都要维护从它自己到AS内其他每一个网络距离的记录,这是一组距离,称为“距离向量D-V”。 …

TypeScript的魔法:如何轻松提升JavaScript项目的稳定性

引言:JavaScript的灵活性与挑战 JavaScript,作为Web开发的核心语言,因其灵活性和广泛的应用受到开发者的喜爱。然而,这种灵活性也带来了挑战,尤其是在大型项目中,代码的维护和错误的追踪变得越来越困难。 …

pdf转换成图片免费软件用哪个?pdf转换成图片就用它

随着技术的发展,现在企业办公运用到的电子文档各种各样,我们日常需要掌握的技能越来越高要求,其中pdf和图片是我们经常接触的文件格式之一,而且这两个文件格式我们会经常将它们进行转换,那么pdf转换成图片怎么操作呢?…

JavaScript 复习

第三章 JavaScript 1 JavaScript的起源 在1995年时,由Netscape公司的Brendan Eich,在网景导航者浏览器上首次设计实现而成。Netscape在最初将其脚本语言命名为LiveScript,因为Netscape与Sun合作,网景公司管理层希望蹭Java的热度…

详解Vue 3 的 Composition API

Vue 3 的 Composition API 是一种新的组合式 API 风格,它可以更好地组织和复用组件逻辑。相比于 Vue 2 的 Options API,Composition API 提供了更灵活和可组合的方式来编写组件。 下面是 Composition API 的一些特点和优势: 函数式组件&…

docker与phpstudy两种方式部署wordpress 并 开启伪静态

实际测试,可能是docker内存限制的缘故,docker部署的会比较卡 下载 wordpress phpstudy phpstudy中伪静态配置 伪静态 正常访问 WordPress 文章页的 URL 地址为 http://asa/index.php?p123。变成伪静态就是http://asa/123.html 。 伪静态是相对真实静…

IDEA2021之后没有Show in Explorer,无法直接打开文件夹,被迁移了

2020版本和更早的版本 目录右键之后,可以出现Show in Explorer。 2021版本和更新的版本 快捷键直接到文件的地址 参考文档

CRM线索公海如何管理?

对于销售和CRM客户管理而言,公海线索的管理极为重要,今天本文将告诉大家: 1、如何合理设置公海线索规则和流程?2、手把手教你完成公海管理系统的搭建 关于CRM的公海管理问题,需要根据企业的具体情况和销售流程来设置…

【网络BSP开发经验】Linux gmac驱动调试

文章目录 Linux网络设备驱动简介Linux网卡驱动网络协议接口层网络设备接口层设备驱动功能层网络设备与媒介层linux驱动数据结构linux驱动注册过程网络设备驱动的注册与注销linux驱动数据包收发流程 Linux PHY驱动MDIO接口PHY简介PHY关联过程PHY状态机对端MAC情况(接…

多个pdf怎么合并成一个pdf?几个超实用方法分享

多个pdf怎么合并成一个pdf?合并多个PDF文件可以使得它们更容易管理和分享。这特别是那些需要以PDF格式与其他人共享文件的人来说是非常有用的。例如,如果你需要将多个文档或报告打包为一个文件并发送给客户或同事,将它们合并为一个PDF文件是非…

14、监测数据采集物联网应用开发步骤(10)

监测数据采集物联网应用开发步骤(9.2) Modbus rtu协议开发 本章节在《监测数据采集物联网应用开发步骤(7)》基础上实现可参考《...开发步骤(7)》调试工具,本章节代码需要调用modbus_tk组件,阅读本章节前建议baidu熟悉modbus rtu协议内容 组件安装modb…

【同步异步可并发日志系统】设计及实现

1. 项⽬介绍2. 开发环境3. 项目核⼼技术4. 环境搭建5. ⽇志系统介绍5.1 为什么需要⽇志系统5.2⽇志系统技术实现5.2.1 同步写⽇志5.2.2 异步写⽇志 6. ⽇志系统框架设计7. 代码设计7.1 实⽤类设计7.2 ⽇志等级类设计7.3 ⽇志消息类设计7.4 ⽇志格式化输出设计思想7.4.1FormatIt…

OpenLayers7官方文档翻译,OpenLayers7中文文档,OpenLayers快速入门

快速入门 这个入门文档向您展示如何放一张地图在web网页上。 开发设置使用 NodeJS(至少需要Nodejs 14 或更高版本),并要求安装 git。 设置新项目 开始使用OpenLayers构建项目的最简单方法是运行:npm create ol-app npm create…

中大许少辉博士后畅销榜《乡村振兴战略下传统村落文化旅游设计》自由营 ​​​

中大许少辉博士后畅销榜《乡村振兴战略下传统村落文化旅游设计》自由营 ​​​

Visual Studio(2022)生成链接过程的.map映射文件以及.map映射文件的内容说明

微软的官方说明 /MAP(生成映射文件) | Microsoft Learn 设置步骤 1. 右键项目属性, 连接器 -> 常规 -> 启用增量链接,设置为否。如下图: 2. 连接器 -> 调试 生成调试信息 设置为 生成调试信息 (/DEBUG) 生成程序数据库…