什么是ZooKeeper?
前言
只有光头才能变强。
文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y
上次写了一篇 什么是消息队列?以后,本来想入门一下Kafka的(装一下环境、看看Kafka一些概念啥的)。后来发现Kafka用到了ZooKeeper,而我又对ZooKeeper不了解,所以想先来学学什么是ZooKeeper,再去看看什么是Kafka。
ZooKeeper相信大家已经听过这个词了,不知道大家对他了解多少呢?我第一次听到ZooKeeper的时候是在学Eureka的时候(外行人都能看懂的SpringCloud,错过了血亏!),同样ZooKeeper也可以作为注册中心。
后面听到ZooKeeper的时候,是因为ZooKeeper可以作为分布式锁的一种实现。
直至在了解Kafka的时候,发现Kafka也需要依赖ZooKeeper。Kafka使用ZooKeeper管理自己的元数据配置。
这篇文章来写写我学习ZooKeeper的笔记,如果有错的地方希望大家可以在评论区指出。
一、什么是ZooKeeper
从上面我们也可以发现,好像哪都有ZooKeeper的身影,那什么是ZooKeeper呢?我们先去官网看看介绍:
官网还有另一段话:
ZooKeeper: A Distributed Coordination Service for Distributed Applications
相比于官网的介绍,我其实更喜欢Wiki中对ZooKeeper的介绍:
(留下不懂英语的泪水)
我简单概括一下:
- ZooKeeper主要服务于分布式系统,可以用ZooKeeper来做:统一配置管理、统一命名服务、分布式锁、集群管理。
- 使用分布式系统就无法避免对节点管理的问题(需要实时感知节点的状态、对节点进行统一管理等等),而由于这些问题处理起来可能相对麻烦和提高了系统的复杂性,ZooKeeper作为一个能够通用解决这些问题的中间件就应运而生了。
二、为什么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的节点我们称之为Znode,Znode分为两种类型:
- 短暂/临时(Ephemeral):当客户端和服务端断开连接后,所创建的Znode(节点)会自动删除
- 持久(Persistent):当客户端和服务端断开连接后,所创建的Znode(节点)不会删除
ZooKeeper和Redis一样,也是C/S结构(分成客户端和服务端)
2.1 监听器
在上面我们已经简单知道了ZooKeeper的数据结构了,ZooKeeper还配合了监听器才能够做那么多事的。
常见的监听场景有以下两项:
- 监听Znode节点的数据变化
- 监听子节点的增减变化
没错,通过监听+Znode节点(持久/短暂[临时]),ZooKeeper就可以玩出这么多花样了。
三、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重启。
做法:我们可以将common.yml这份配置放在ZooKeeper的Znode节点中,系统A、B、C监听着这个Znode节点有无变更,如果变更了,及时响应。
参考资料:
- 基于zookeeper实现统一配置管理
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去访问。
3.3 分布式锁
锁的概念在这我就不说了,如果对锁概念还不太了解的同学,可参考下面的文章
我们可以使用ZooKeeper来实现分布式锁,那是怎么做的呢??下面来看看:
系统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要考虑的事没那么简单的,后面有机会深入的话,我还会继续分享,希望这篇文章对大家有所帮助~
参考资料:
- 分布式服务框架 Zookeeper
- ZooKeeper初识整理(老酒装新瓶)
- ZooKeeper
- ZooKeeper 的应用场景
- https://zhuanlan.zhihu.com/p/59669985
乐于输出干货的Java技术公众号:Java3y。公众号内有200多篇原创技术文章、海量视频资源、精美脑图,不妨来关注一下!
觉得我的文章写得不错,不妨点一下赞!
什么是ZooKeeper?的更多相关文章
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- [译]ZOOKEEPER RECIPES-Leader Election
选主 使用ZooKeeper选主的一个简单方法是,在创建znode时使用Sequence和Ephemeral标志.主要思想是,使用一个znode,比如"/election",每个客 ...
- zookeeper源码分析之六session机制
zookeeper中session意味着一个物理连接,客户端连接服务器成功之后,会发送一个连接型请求,此时就会有session 产生. session由sessionTracker产生的,sessio ...
- zookeeper源码分析之五服务端(集群leader)处理请求流程
leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...
- zookeeper源码分析之四服务端(单机)处理请求流程
上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...
- zookeeper源码分析之三客户端发送请求流程
znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...
- zookeeper源码分析之二客户端启动
ZooKeeper Client Library提供了丰富直观的API供用户程序使用,下面是一些常用的API: create(path, data, flags): 创建一个ZNode, path是其 ...
- zookeeper源码分析之一服务端启动过程
zookeeper简介 zookeeper是为分布式应用提供分布式协作服务的开源软件.它提供了一组简单的原子操作,分布式应用可以基于这些原子操作来实现更高层次的同步服务,配置维护,组管理和命名.zoo ...
- zookeeper集群的搭建以及hadoop ha的相关配置
1.环境 centos7 hadoop2.6.5 zookeeper3.4.9 jdk1.8 master作为active主机,data1作为standby备用机,三台机器均作为数据节点,yarn资源 ...
- 如何编译Zookeeper源码
1. 安装Ant Ant下载地址:http://ant.apache.org/bindownload.cgi 解压即可. 2. 下载Zookeeper源码包 https://github.com/ap ...
随机推荐
- 学习ASP.NET Core Razor 编程系列九——增加查询功能
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
- Java面向对象(二、继承)
Java 继承 继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法 ...
- 杨校老师课堂之JavaScript右下角广告弹框教程
案例制作思路: 1.先制作界面 添加一个盒子包含一个按钮,使盒子绝对定位在右上角 添加一个大盒子,同理,将盒子居于左下角:其中内部包含一个顶端盒子和底部盒子 顶端盒子因为是属于大盒子内部的存在,所以宽 ...
- 命令行备忘录 cli-memo
前言 有时候想用一个简洁点儿的备忘录,发现没有简洁好用的,于是就想着开发一个,秉着简洁 的思想,所以连界面都没有,只能通过命令行来操作(尽可能的将命令简化).设计的时候 借鉴了git分支的思想,每个备 ...
- java读取.properties配置文件的几种方法
读取.properties配置文件在实际的开发中使用的很多,总结了一下,有以下几种方法(仅仅是我知道的):一.通过jdk提供的java.util.Properties类.此类继承自java.util. ...
- Linux设置开放一个端口
修改防火墙配置需要修改 /etc/sysconfig/iptables 这个文件,如果要开放哪个端口,在里面添加一条. -A RH-Firewall-1-INPUT -m state --state ...
- SSM框架+MySql保存emoji表情
本博客的记录的操作在linux 项目中需要从微信获取授权来登录,在此过程,保存微信emoji表情昵称到mysql数据库的时候出了错误. 老规矩百度一下,得知是mysql的utf8字符集只支持1-3个字 ...
- ARP攻击之Kali Linux局域网断网攻击
特别声明: 我们学习研究网络安全技术的目的应是为了维护网络世界的安全,保护自己和他人的私有信息不被非法窃取和传播.请您遵守您所在地的法律,请勿利用本文所介绍的相关技术做背离道德或者违反法律的事情. S ...
- Mac下安装git
gti下载地址 https://git-scm.com/downloads 一步一步来就完事了.安装完以后执行 git version 查看是否更新到了该版本
- indexer.go
package) ; , ].DocId,:],)) :],) :], , ] ; ];]--],]) , ) )) )-b+b*d/avgDocLength)) , ;].locations[ind ...