什么是ZooKeeper?

前言

只有光头才能变强。

文本已收录至个人GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3yhtml

上次写了一篇 什么是消息队列?之后,原本想入门一下Kafka的(装一下环境、看看Kafka一些概念啥的)。后来发现Kafka用到了ZooKeeper,而我又对ZooKeeper不了解,因此想先来学学什么是ZooKeeper,再去看看什么是Kafka。java

ZooKeeper相信你们已经听过这个词了,不知道你们对他了解多少呢?我第一次听到ZooKeeper的时候是在学Eureka的时候(外行人都能看懂的SpringCloud,错过了血亏!),一样ZooKeeper也能够做为注册中心node

后面听到ZooKeeper的时候,是由于ZooKeeper能够做为分布式锁的一种实现。git

直至在了解Kafka的时候,发现Kafka也须要依赖ZooKeeper。Kafka使用ZooKeeper管理本身的元数据配置github

这篇文章来写写我学习ZooKeeper的笔记,若是有错的地方但愿你们能够在评论区指出。数据结构

1、什么是ZooKeeper

从上面咱们也能够发现,好像哪都有ZooKeeper的身影,那什么是ZooKeeper呢?咱们先去官网看看介绍:架构

官网对ZooKeeper的介绍

官网还有另外一段话:框架

ZooKeeper: A Distributed Coordination Service for Distributed Applications

相比于官网的介绍,我其实更喜欢Wiki中对ZooKeeper的介绍:分布式

wiki介绍ZooKeeper

(留下不懂英语的泪水)学习

我简单归纳一下:

  • ZooKeeper主要服务于分布式系统,能够用ZooKeeper来作:统一配置管理、统一命名服务、分布式锁、集群管理。
  • 使用分布式系统就没法避免对节点管理的问题(须要实时感知节点的状态、对节点进行统一管理等等),而因为这些问题处理起来可能相对麻烦和提升了系统的复杂性,ZooKeeper做为一个可以通用解决这些问题的中间件就应运而生了。

2、为何ZooKeeper能干这么多?

从上面咱们能够知道,能够用ZooKeeper来作:统一配置管理、统一命名服务、分布式锁、集群管理。

  • 这里咱们无论统一配置管理、统一命名服务、分布式锁、集群管理每一个具体的含义(后面会讲)

那为何ZooKeeper能够干那么多事?来看看ZooKeeper到底是何方神物,在Wiki中其实也有提到:

ZooKeeper nodes store their data in a hierarchical name space, much like a file system or a tree) data structure

ZooKeeper的数据结构,跟Unix文件系统很是相似,能够看作是一颗,每一个节点叫作ZNode。每个节点能够经过路径来标识,结构图以下:

ZooKeeper结构图

那ZooKeeper这颗"树"有什么特色呢??ZooKeeper的节点咱们称之为Znode,Znode分为两种类型:

  • 短暂/临时(Ephemeral):当客户端和服务端断开链接后,所建立的Znode(节点)会自动删除
  • 持久(Persistent):当客户端和服务端断开链接后,所建立的Znode(节点)不会删除
ZooKeeper和Redis同样,也是C/S结构(分红客户端和服务端)

Znode和Znode的类型

2.1 监听器

在上面咱们已经简单知道了ZooKeeper的数据结构了,ZooKeeper还配合了监听器才可以作那么多事的。

常见的监听场景有如下两项:

  • 监听Znode节点的数据变化
  • 监听子节点的增减变化

监听Znode节点的数据有无变化

监听子节点的增减变化

没错,经过监听+Znode节点(持久/短暂[临时]),ZooKeeper就能够玩出这么多花样了。

3、ZooKeeper是怎么作到的?

下面咱们来看看用ZooKeeper怎么来作:统一配置管理、统一命名服务、分布式锁、集群管理。

3.1 统一配置管理

好比咱们如今有三个系统A、B、C,他们有三份配置,分别是ASystem.yml、BSystem.yml、CSystem.yml,而后,这三份配置又很是相似,不少的配置项几乎都同样。

  • 此时,若是咱们要改变其中一份配置项的信息,极可能其余两份都要改。而且,改变了配置项的信息极可能就要重启系统

因而,咱们但愿把ASystem.yml、BSystem.yml、CSystem.yml相同的配置项抽取出来成一份公用的配置common.yml,而且即使common.yml改了,也不须要系统A、B、C重启。

系统A、B、C都使用着这份配置

作法:咱们能够将common.yml这份配置放在ZooKeeper的Znode节点中,系统A、B、C监听着这个Znode节点有无变动,若是变动了,及时响应。

系统A、B、C监听着ZooKeeper的节点,一旦common.yml内容有变化,及时响应

参考资料:

3.2 统一命名服务

统一命名服务的理解其实跟域名同样,是咱们为这某一部分的资源给它取一个名字,别人经过这个名字就能够拿到对应的资源。

好比说,如今我有一个域名www.java3y.com,但我这个域名下有多台机器:

  • 192.168.1.1
  • 192.168.1.2
  • 192.168.1.3
  • 192.168.1.4

别人访问www.java3y.com便可访问到个人机器,而不是经过IP去访问。

经过名称去访问旗下的IP

3.3 分布式锁

锁的概念在这我就不说了,若是对锁概念还不太了解的同窗,可参考下面的文章

咱们可使用ZooKeeper来实现分布式锁,那是怎么作的呢??下面来看看:

系统A、B、C都去访问/locks节点

系统A、B、C都去访问locks节点

访问的时候会建立带顺序号的临时/短暂(EPHEMERAL_SEQUENTIAL)节点,好比,系统A建立了id_000000节点,系统B建立了id_000002节点,系统C建立了id_000001节点。

建立出临时带顺序号的节点

接着,拿到/locks节点下的全部子节点(id_000000,id_000001,id_000002),判断本身建立的是否是最小的那个节点

  • 若是是,则拿到锁。

    • 释放锁:执行完操做后,把建立的节点给删掉
  • 若是不是,则监听比本身要小1的节点变化

举个例子:

  • 系统A拿到/locks节点下的全部子节点,通过比较,发现本身(id_000000),是全部子节点最小的。因此获得锁
  • 系统B拿到/locks节点下的全部子节点,通过比较,发现本身(id_000002),不是全部子节点最小的。因此监听比本身小1的节点id_000001的状态
  • 系统C拿到/locks节点下的全部子节点,通过比较,发现本身(id_000001),不是全部子节点最小的。因此监听比本身小1的节点id_000000的状态
  • …...
  • 等到系统A执行完操做之后,将本身建立的节点删除(id_000000)。经过监听,系统C发现id_000000节点已经删除了,发现本身已是最小的节点了,因而顺利拿到锁
  • ….系统B如上

3.4集群状态

通过上面几个例子,我相信你们也很容易想到ZooKeeper是怎么"感知"节点的动态新增或者删除的了。

仍是以咱们三个系统A、B、C为例,在ZooKeeper中建立临时节点便可:

各维护一个临时节点

只要系统A挂了,那/groupMember/A这个节点就会删除,经过监听groupMember下的子节点,系统B和C就可以感知到系统A已经挂了。(新增也是同理)

除了可以感知节点的上下线变化,ZooKeeper还能够实现动态选举Master的功能。(若是集群是主从架构模式下)

原理也很简单,若是想要实现动态选举Master的功能,Znode节点的类型是带顺序号的临时节点(EPHEMERAL_SEQUENTIAL)就行了。

  • Zookeeper会每次选举最小编号的做为Master,若是Master挂了,天然对应的Znode节点就会删除。而后让新的最小编号做为Master,这样就能够实现动态选举的功能了。

最后

这篇文章主要讲解了ZooKeeper的入门相关的知识,ZooKeeper经过Znode的节点类型+监听机制就实现那么多好用的功能了!

固然了,ZooKeeper要考虑的事没那么简单的,后面有机会深刻的话,我还会继续分享,但愿这篇文章对你们有所帮助~

参考资料:

乐于输出 干货的Java技术公众号:Java3y。公众号内有200多篇 原创技术文章、海量视频资源、精美脑图,不妨来 关注一下!

帅的人都关注了

以为个人文章写得不错,不妨点一下

相关文章
相关标签/搜索