ZooKeeper论文阅读笔记
介绍
ZooKeeper 是一个开源的分布式协调服务,它提供了高可用性和一致性的数据管理和协调功能。它被设计用于构建可靠的分布式系统,并提供了一组简单而强大的 wait-free 原语,使开发人员能够处理分布式应用中的共享配置、命名服务、分布式锁、分布式队列等问题。
在论文中,客户端表示使用 Zookeeper 服务的应用,服务端表示一个运行 Zookeeper 程序的程序,znode 表示内存中的数据节点(Zookeeper 使用树形结构作为存储结构,整体就像一个文件系统)。
Zookeeper服务概述

znode 有两种类型:
- 常规:数据对象正常创建和删除
- 临时:创建对象的 session 终止之后,对象会被删除
znode 默认最大存储 1MB 数据,这是可配置的。
在创建文件的时候设置 SEQUENTIAL 标志,那么会在文件名后增加一个自动增加的计数器。比如上图创建 /app1 节点时设置了 SEQUENTIAL 标志,那么连续创建三个 /app1/p_ 节点时结果如上图所示。ZooKeeper 实现了观测(watch)机制,能够在数据对象更新后通知客户端(由与客户端连接的服务端通知),观测只会触发一次,如果想继续监测需要重新设置 watch。
ZooKeeper 以库的形式向客户端提供 API,类似于 RPC 中的 client stub,库也负责客户端到 ZooKeeper 服务器的连接,每个连接即是一个 session,它有一个超时时间 s,如果在超时时间内没有收到客户端请求,那么服务器认为客户端出故障,客户端即便没有读写请求也要发送心跳避免超时。为了防止会话超时,ZooKeeper 客户端库在会话空闲 \(\frac{s}{3}\) 后发送心跳,如果在 \(\frac{2s}{3}\) 内没有收到服务器的消息,则切换到新服务器,
其中 s 是以毫秒为单位的会话超时
客户端API
create(path, data, flags):创建一个路径为path的 znode,将data[]保存到其中,返回新 znode 的名称,flags用来设置 znode 类型:普通或者临时,以及设置SEQUENTIAL标志。delete(path, version):如果版本匹配,删除path对应的 znode。exists(path, watch):如果path对应的 znode 存在,那么返回真,否则返回假。watch标志让客户端观测这个 znode。getData(path, watch):返回 znode 对应的数据和元数据,watch功能类似。setData(path, data, version):如果版本匹配,将data[]写入到path对应的 znode 中。getChildren(path, watch):返回 znode 的子节点集合。sync(path):等待目前所有未决的更新,path没什么用。
以上全部的方法提供了阻塞版本和非阻塞版本,如果传入版本号为-1,那么不进行版本检查。
Zookeeper保证
Zookeeper 给出了两个保证:
- 线性写入:所有改变 ZooKeeper 状态的更新都是串行的
- 客户端先进先出:所有来自客户端的请求按照先进先出顺序执行
Zookeeper 并不完全满足线性一致性,它只支持写请求的线性一致性,以及保证一个客户端的读操作一定可以读取到该客户端最后一个写操作的数据或者在这个写操作之后的其它客户端的写入数据,这是通过为每个写操作分配一个 zxid 来实现,zxid 是单调递增的,写请求的响应包含该写请求对应的 zxid,服务器将该写请求修改的 znode 的最近修改信息更新为该zxid(这句话是我的猜测),之后客户端发出读请求要求服务器读取的 znode 的 zxid 不小于客户端最近一次读/写请求返回的 zxid,如果该服务器在一定时间内还不能满足该要求,那么客户端会连接其它的服务器获取数据。
ZooKeeper 服务包含一组使用复制来实现高可用性和性能的服务器。ZooKeeper 使用简单的流水线架构实现,该架构允许 ZooKeeper 处理成百上千个未完成的请求,同时仍能实现低延迟。 这样的管道自然能够以 FIFO 顺序从单个客户端执行操作。 保证 FIFO 客户端顺序使客户端能够异步提交操作。 通过异步操作,客户端可以同时进行多个未完成的操作。
为了满足线性写入,Zookeeper 实现了一个 leader-based 的原子广播协议 ZAB,该协议改良自 Paxos 协议。
对于写入请求,如果与客户端连接的服务器是 Follower 节点,那么它会把请求转发给 Leader 服务器,如果是同步写,那么当写请求应用到超过半数服务器时返回响应给客户端,如果是异步写,那么立即返回成功响应给客户端。
对于读操作,不用转发给 Leader,直接返回服务器本地存储的数据即可。这样可能造成返回的数据不是最新的,但这是 ZooKeeper 可以容忍的。如果客户端想要最新的数据,那么它可以先发送一个 Sync 请求,该请求可以看作是一个空的写请求,由于 Zookeeper 的两个保证,在执行完 Sync 后再执行读操作就可以读取到所有在 Sync 之前执行的写请求数据了。
现在举个例子演示这两个保证如何保障系统运行。假设一个系统选举主节点管理其他节点,主节点随后需要更新一些配置,然后通知其他节点,要求:
- 主节点在修改配置过程,不希望其他节点访问正在被修改的配置
- 主节点在更新完成前崩溃,不希望其他节点访问这些破碎的配置
可以设置一个readyznode解决,主节点可以在配置前删除,完成后重新建立。当其他节点看到ready不存在时就不读取配置。
但是还会存在问题:如果其他节点看到ready后读取配置,但是主节点随即删除ready节点并开始修改配置,那么其他节点将得到过时的配置。这个问题可以采用 watch 机制来解决,ready删除后会及时通知其他节点,这样客户端就会放弃读取的数据,然后重新设置 watch,当配置文件更新完毕后通知客户端发送读取请求。
原语示例:
配置管理:只需要将配置保存在一个 znode 中,各个进程可以通过 watch 机制来获取配置更新通知。
组成员关系:组成员进程上线之后可以在组对应的 znode 之下创建对应的临时子 znode,成员进程退出之后临时znode也被删除,因此可以通过组 znode 的子znode获取组成员状态。
简单锁:应用试图创建同一个文件,如果 znode 创建成功,那么获取锁。如果 znode 已经存在,那么需要等待锁被释放(znode被删除)后才能继续尝试获取锁(创建znode)。
无惊群效应的简单锁:简单锁会出现大量进程竞争的情况,因为每次锁被释放后所有等待的进程都会被通知唤醒,但最终只有一个进程可以获取锁,可以将锁请求排序后,按次序分配锁,实现公平锁,如下面的算法所示:
Lock (l是 znode 路径)
1 n = create(l + “/lock-”, EPHEMERAL|SEQUENTIAL)
2 C = getChildren(l, false)
3 if n is lowest znode in C, exit
4 p = znode in C ordered just before n
5 if exists(p, true) wait for watch event
6 goto 2
Unlock
1 delete(n)
读写锁:写锁和普通锁类似,和其他的锁互斥。读锁之间可以互相兼容,和写锁互斥。
Write Lock
1 n = create(l + “/write-”, EPHEMERAL|SEQUENTIAL)
2 C = getChildren(l, false)
3 if n is lowest znode in C, exit
4 p = znode in C ordered just before n
5 if exists(p, true) wait for event
6 goto 2
Read Lock
1 n = create(l + “/read-”, EPHEMERAL|SEQUENTIAL)
2 C = getChildren(l, false)
3 if no write znodes lower than n in C, exit
4 p = write znode in C ordered just before n
5 if exists(p, true) wait for event
6 goto 3
双栅栏:双栅栏用来保证多个客户端的计算同时开始和同时结束。客户端开始计算之前添加 znode 到栅栏对应的 znode 之下,结束计算之后删除 znode。客户端需要等待栅栏 znode 的子 znode 数量到达一定阈值后才能开始计算,客户端可以等待一个特殊的
ready的 znode 的创建,当数量到达阈值后创建。客户端退出的时候需要等待子 znode 全部被删除,同样可以通过删除ready删除。
Zookeeper实现
ZooKeeper 的组件如下图所示,ZooKeeper 的数据副本保存在每一个服务器的内存中,写操作需要通过一致性协议提交到数据库,而读取请求可以直接访问服务器本地数据库获得。ZooKeeper 在写请求修改到数据库之前会先将其写入日志(WAL)中,并在适当的时机持久化当前数据块的快照,故障后采用快照加日志的方式进行恢复。根据一致协议,写入请求会转发到领导(leader)节点。

请求处理器
请求处理器收到写入请求之后,会将其转换为事务,与客户端发送的请求不同,事务是幂等的。 当领导者收到写入请求时,它会计算应用写入时系统的状态,并将其转换为捕获此新状态的事务。 必须计算未来状态,因为可能有尚未应用到数据库的未完成事务。 例如,如果客户端执行条件 setData 并且请求中的版本号与正在更新的 znode 的未来版本号相匹配,则该服务会生成一个包含新数据、新版本号和更新时间戳的 setDataTXN。 如果发生错误,例如版本号不匹配或要更新的 znode 不存在,则会生成 errorTXN。
原子广播(Atomic Broadcast)
所有更新 ZooKeeper 状态的请求都被转发给领导者。 领导者执行请求并通过原子广播协议 Zab 广播 ZooKeeper 的状态变化。 接收到客户端请求的服务器在接收到相应的状态变化时响应客户端。 Zab 默认使用 majority quorums 来决定提案,因此 Zab 和 ZooKeeper 只能在大多数服务器正确的情况下工作。Zab 保证领导者广播的更改按照发送的顺序进行交付,并且在广播自己的更改之前,先前领导者的所有更改都已交付给现在的领导者
ZAB 使用 TCP 协议传输数据,而 TCP 协议可以保证传输的数据按照发送顺序到达。
在正常操作期间,Zab 确实按顺序传递所有消息,并且只传递一次,但由于 Zab 不会持久记录传递的每条消息的 ID,因此 Zab 可能会在恢复期间重新传递消息。 因为使用的是幂等事务,多次投递是可以接受的,只要按顺序投递即可。 事实上,ZooKeeper 要求 Zab 至少重新投递上次快照开始后投递的所有消息
多副本数据库
当服务器故障后,使用周期性的快照和快照之后的日志恢复。创建快照的时候并不需要锁定数据库,相反,Zookeeper 通过优先深度搜索遍历 data-tree 中znode 里的数据并持久化到磁盘中,由于生成的快照可能应用了快照生成期间交付的状态更改的某些子集,因此结果可能与 ZooKeeper 在任何时间点的状态都不对应。 但是,由于状态更改是幂等的,只要我们按顺序应用状态更改,我们就可以应用它们两次。
例如,假设现在有两个 znode 节点分别为 /foo 和 /goo,这两个节点分别存储了数据 f1 和 g1,且版本号都为 1。此时开始生成快照,然后按序执行以下三个操作,操作序列含义为<transactionType,path,value,new-version>,此时快照检测点的位置不包含下面的操作序列。
- <SetFDataTrx,/foo,f2,2>
- <SetFDataTrx,/goo,g2,2>
- <SetFDataTrx,/foo,f3,3>
处理完这些状态更改后,/foo 和 /goo 的值分别为版本 3 和版本 2 的 f3 和 g2。 然而,快照可能记录了 /foo 和 /goo 分别具有版本 3 和 1 的值 f3 和 g1,这不是 ZooKeeper 数据树的有效状态。 但如果服务器崩溃并使用此快照恢复,然后 Zab执行检查点后的日志重新提交上面的三个操纵,则生成的状态可以正确对应崩溃前的服务状态。
参考博客:https://juejin.cn/post/6844903891146915848
ZooKeeper论文阅读笔记的更多相关文章
- 论文阅读笔记 - Mesos: A Platform for Fine-Grained ResourceSharing in the Data Center
作者:刘旭晖 Raymond 转载请注明出处 Email:colorant at 163.com BLOG:http://blog.csdn.net/colorant/ 更多论文阅读笔记 http:/ ...
- 论文阅读笔记 - YARN : Architecture of Next Generation Apache Hadoop MapReduceFramework
作者:刘旭晖 Raymond 转载请注明出处 Email:colorant at 163.com BLOG:http://blog.csdn.net/colorant/ 更多论文阅读笔记 http:/ ...
- 论文阅读笔记 Word Embeddings A Survey
论文阅读笔记 Word Embeddings A Survey 收获 Word Embedding 的定义 dense, distributed, fixed-length word vectors, ...
- 论文阅读笔记 Improved Word Representation Learning with Sememes
论文阅读笔记 Improved Word Representation Learning with Sememes 一句话概括本文工作 使用词汇资源--知网--来提升词嵌入的表征能力,并提出了三种基于 ...
- [置顶]
人工智能(深度学习)加速芯片论文阅读笔记 (已添加ISSCC17,FPGA17...ISCA17...)
这是一个导读,可以快速找到我记录的关于人工智能(深度学习)加速芯片论文阅读笔记. ISSCC 2017 Session14 Deep Learning Processors: ISSCC 2017关于 ...
- Nature/Science 论文阅读笔记
Nature/Science 论文阅读笔记 Unsupervised word embeddings capture latent knowledge from materials science l ...
- 论文阅读笔记(二十一)【CVPR2017】:Deep Spatial-Temporal Fusion Network for Video-Based Person Re-Identification
Introduction (1)Motivation: 当前CNN无法提取图像序列的关系特征:RNN较为忽视视频序列前期的帧信息,也缺乏对于步态等具体信息的提取:Siamese损失和Triplet损失 ...
- 论文阅读笔记(十八)【ITIP2019】:Dynamic Graph Co-Matching for Unsupervised Video-Based Person Re-Identification
论文阅读笔记(十七)ICCV2017的扩刊(会议论文[传送门]) 改进部分: (1)惩罚函数:原本由两部分组成的惩罚函数,改为只包含 Sequence Cost 函数: (2)对重新权重改进: ① P ...
- [论文阅读笔记] GEMSEC,Graph Embedding with Self Clustering
[论文阅读笔记] GEMSEC: Graph Embedding with Self Clustering 本文结构 解决问题 主要贡献 算法原理 参考文献 (1) 解决问题 已经有一些工作在使用学习 ...
- [论文阅读笔记] metapath2vec: Scalable Representation Learning for Heterogeneous Networks
[论文阅读笔记] metapath2vec: Scalable Representation Learning for Heterogeneous Networks 本文结构 解决问题 主要贡献 算法 ...
随机推荐
- [jenkins]简介与安装
前言 jenkins是一种代码构建平台,一般用于CI/CD中的CI部分,当然也可以集成CD功能. 安装 环境 IP:192.168.0.10 系统:centos 7 快速安装步骤 官网下载jenkin ...
- 利用IPV6随时访问家中影音Jellyfin
本文章主要记录通过ipv6实现家庭影音中心在互联网上的访问. 之前很多方案都是通过第三方进行内网穿透,实际体验不是很好.目前ipv6发展迅速,完全可以取代这种以ipv4为中心的内网资源外网访问的方式. ...
- 产品代码都给你看了,可别再说不会DDD(三):战略设计
这是一个讲解DDD落地的文章系列,作者是<实现领域驱动设计>的译者滕云.本文章系列以一个真实的并已成功上线的软件项目--码如云(https://www.mryqr.com)为例,系统性地讲 ...
- 领域驱动设计(DDD):从基础代码探讨高内聚低耦合的演进
大家好,我是付威,一名已在编码第一线奋斗了十余年的程序员.在2019年我初次接触到领域驱动设计(Domain-Driven Design,简称DDD)的概念.在我的探索中,我发现许多有关DDD的教程过 ...
- 论文解读(AdSPT)《Adversarial Soft Prompt Tuning for Cross-Domain Sentiment Analysis》
Note:[ wechat:Y466551 | 可加勿骚扰,付费咨询 ] 论文信息 论文标题:Adversarial Soft Prompt Tuning for Cross-Domain Senti ...
- Linux 干货整理(持续更新)
博客地址:https://www.cnblogs.com/zylyehuo/ 如果虚拟机开机没有 ip 怎么办 1.vim编辑网卡配置文件,修改如下参数 [root@s25linux tmp]# cd ...
- 国内镜像安装Python解释器及扩展包
一.下载Python解释器 1.下载地址 官网(下载速度很慢):Welcome to Python.org 淘宝镜像(推荐):CNPM Binaries Mirror (npmmirror.com) ...
- Jmeter获取Websocket多帧消息的实现方法
由于需要对WebSocket进行压力测试,因此又回归到了JMeter的使用.网络上缺少具体的获取多帧消息的操作,且自己也踩了两个坑,总结一下可行的操作供大家参考. 一.情况说明 ...
- 部分网页中仅供浏览的pdf文件下载方法
现在越来越多的网站提供的PDF资料只能在线浏览,不提供下载功能,实际上仅仅是通过网页PDF浏览插件来访问文件资源,如果能够获取到该文件的访问地址,就可以访问下载. 以Firefox浏览器访问某大学网站 ...
- Solution Set -「ARC 116」(in progress)
「ARC 116A」Odd vs Even Link. 看 \(n\) 有多少 \(2\) 因子. // Problem: A - Odd vs Even // Contest: AtCoder - ...