ZooKeeper简介及其并发读写情况分析

1 前言

谈到分布式应用,就离不开ZooKeeper,那么ZooKeeper是怎么来的,它又是做什么的?通过这篇文章,希望大家最ZooKeeper有个基本的了解。
本篇文章主要介绍ZooKeeper的基本概念及其在并发情况下的读写流程分析,希望能对大家有所帮助!

2 ZooKeeper简介

2.1 背景

众所周知,分布式应用程序都需要一个协调服务,那么为什么分布式应用程序需要协调服务呢?因为分布式应用程序是分布在多台主机上面的,分布在多台主机上面的应用要想共同地去很好地完成任务,当然得需要一个协调者了,ZooKeeper就是这样一个协调者。其实分布式应用程序就跟团队一样,团队要想高效的完成任务,当然需要一个协调者去协调各项工作了,这个协调者就是团队Leader啦。
我们都知道协调者不是这么好当的,对于分布式应用程序来说也是如此,协调服务很容易出现竞态条件、死锁等问题。为了减少分布式应用程序开发协调服务的成本,所以就诞生了ZooKeeper——开源的分布式协调服务。

2.2 基本概念

ZooKeeper 是一个开源的分布式协调服务,由雅虎创建,是 Google Chubby 的开源实现。分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅、命名服务、分布式协调/通知、集群管理、配置维护、分布式锁等功能。

2.3 特点

1、简单

分布式应用程序可以通过一个共享的层级命名空间(类似标准的文件系统)来进行协调,该层级命名空间由数据节点构成——在ZooKeeper中我们称它为znode,znode类似标准文件系统中的文件或是目录。不同于标准文件系统,ZooKeeper中的数据是存在在内存中的,所以ZooKeeper可以实现高吞吐量和低延迟。

2、基于复制

ZooKeeper集群中的server是互相复制的,所以集群中的每个server数据都是一样的,正因如此,我们可以通过任意server来读取数据。


ZooKeeper集群中的主机是互相复制的

集群中的server必须能够互相感知,它们拥有相同的状态。客户端可以连接任意server,然后与server保持着TCP连接,通过此连接可以发送请求、获得响应,当此连接断掉的时候,客户端会重新连接一个不同的server。
集群中每一个server都可以服务客户端,读请求通过每个server的本地数据副本来提供,写请求则由ZooKeeper协议来处理。作为协议的一部分,所有的写请求都会被转发到集群中一个叫做Leader的节点来处理,集群中的其余节点则称为Follower,Follower用来接收并处理来自Leader的提案。Leader宕机重新选举与Follower与Leader的同步也都是此协议的内容,感兴趣可以搜索ZooKeeper zab协议进一步了解。

3、有序性

ZooKeeper通过为每一个更新操作编号来保证事务有序性。

4、快速

ZooKeeper在读多写少的场景中,拥有极快的速度。

2.4 数据模型

ZooKeeper的数据模型是层次型,类似文件系统。


ZooKeeper的数据模型

每个数据节点,在ZooKeeper中叫做znode,并且其有一个唯一的路径标识,znode既可以包含数据也可以包含子节点,好比文件系统中允许文件也作为目录一样。znode中数据的读写都是原子的。
ZooKeeper中也有临时节点的概念,只要创建临时节点的会话存在,该节点就存在,会话一结束,那么该节点就会被删除。

2.5 ZooKeeper的一些保证

作为构建复杂分布式服务的基础,ZooKeeper提供了一些保证,利用这些保证,我们可以保证应用的正确性:

  • 顺序一致性:来自同一客户端的更新将按顺序进行。
  • 原子性:更新操作要么成功要么失败,不存在中间状态。
  • 单系统映像:不论连接到哪个服务器,客户端都会看到相同的视图,因为ZooKeeper是基于复制的嘛。
  • 可靠性:更新操作成功后,znode状态会一直持续到下次更新操作,在此期间,状态不变。
  • 及时性:客户端会及时获取ZooKeeper最新状态。

3 ZooKeeper的读写流程分析

在了解了ZooKeeper的基本概念后,我们来详细看下ZooKeeper的读写流程,以及ZooKeeper在并发情况下的读写控制。以求对ZooKeeper有进一步的了解。

3.1 读流程分析

读流程如下图所示:


ZooKeeper读流程

因为ZooKeeper集群中所有的server节点都拥有相同的数据,所以读的时候可以在任意一台server节点上,客户端连接到集群中某一节点,读请求,然后直接返回。当然因为ZooKeeper协议的原因(一半以上的server节点都成功写入了数据,这次写请求便算是成功),读数据的时候可能会读到数据不是最新的server节点,所以比较推荐使用watch机制,在数据改变时,及时感应到。

3.2 写流程分析

写流程如下图所示:


ZooKeeper写流程

当一个客户端进行写数据请求时,会指定ZooKeeper集群中的一个server节点,如果该节点为Follower,则该节点会把写请求转发给Leader,Leader通过内部的协议进行原子广播,直到一半以上的server节点都成功写入了数据,这次写请求便算是成功,然后Leader便会通知相应Follower节点写请求成功,该节点向client返回写入成功响应。

3.3 ZooKeeper并发读写情况分析

我们已经知道ZooKeeper的数据模型是层次型,类似文件系统,不过ZooKeeper的设计目标定位是简单、高可靠、高吞吐、低延迟的内存型存储系统,因此它的value不像文件系统那样适合保存大的值,官方建议保存的value大小要小于1M,key为路径。

ZooKeeper的数据模型

每个数据节点在ZooKeeper中叫做znode,并且其有一个唯一的路径标识,znode节点可以包含数据和子节点。

ZooKeeper的层次模型是通过ConcurrentHashMap实现的,key为path,value为DataNode,DataNode保存了znode中的value、children、 stat等信息。

ZooKeeper的层次模型是通过ConcurrentHashMap实现的,而ConcurrentHashMap是线程安全的Hash Table,它采用了锁分段技术来减少锁竞争,提高性能的同时又保证了并发安全,其结构如下图所示:

ConcurrentHashMap结构

ConcurrentHashMap由两部分组成,Segment和HashEntry,锁的粒度是Segment,每个Segment 对象包含整个散列映射表的若干个桶,散列冲突时通过链表来解决。

因为插入键 / 值对操作只是在 Segment 包含的某个桶中完成,所以这里的加锁操作是针对(键的 hash 值对应的)某个具体的 Segment,不需要锁定整个ConcurrentHashMap,所以对于ConcurrentHashMap,可以进行并发的写操作,只要写入的Segment不同。而所有的读线程几乎不会因为写操作的加锁而阻塞(除非读线程刚好读到这个 Segment 中某个 HashEntry 的 value 域的值为 null,此时需要加锁后重新读取该值。这便是锁分段技术,保证并发安全的情况下又提高了性能。

对于ZooKeeper来讲,ZooKeeper的写请求由Leader处理,Leader能够保证并发写入的有序性,即同一时刻,只有一个写操作被批准,然后对该写操作进行全局编号,最后进行原子广播写入,所以ZooKeeper的并发写请求是顺序处理的,而底层又是用了ConcurrentHashMap,理所当然写请求是线程安全的。而对于并发读请求,同理,因为用了ConcurrentHashMap,当然也是线程安全的了。总结来说,ZooKeeper的并发读写是线程安全的。
但是对于ZooKeeper的客户端来讲,如果使用了watch机制,在进行了读请求但是watch znode前这段时间中,如果znode的数据变化了,客户端是无法感知到的,这段时间客户端的数据就有一定的滞后性了,只有当下次数据变化后,客户端才能感知到,所以对于客户端来说,数据是最终一致性。

4 总结

通过上述阅读,相信大家对ZooKeeper的基本概念与读写流程都有了一定的了解。这篇文章内容不算多,但却花了我不少时间,主要时间花在了对知识、概念正确性的考察上面,尽力避免因为我的理解错误而误导大家。最后,文章有什么不正确的地方,感谢大家的指出,如果文章对你有帮助,也欢迎点赞。

5 参考资料

[1] ZooKeeper官方文档资料. http://zookeeper.apache.org/doc/current/zookeeperOver.html.
[2] zookeeper的原理和应用场景. https://www.jianshu.com/p/b48d50e1fcb1.
[3] 探索 ConcurrentHashMap 高并发性的实现机制. https://www.ibm.com/developerworks/cn/java/java-lo-concurrenthashmap/.

6 写在最后

聊技术,不止于技术

欢迎大家关注我的个人公众号:WU双,在这里我会与大家分享技术文章、管理知识以及个人的一些思想感悟。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容