zookeeper知识点总结
什么是Zookeeper:
zookeeper是一个开源的分布式协同系统,可以用来管理不太容易控制的分布式服务,组成一个高级可用的集群服务.
zookeeper提供了一系列API接口供业务使用.
主要使用场景:配置服务(统一配置管理),命名服务,集群管理,分布式锁,分布式队列等
官网中所说,zookeeper致力于开发和维护成为一个高度可靠的分布式协调器。
zookeeper能干什么:
- 分布式锁,zookeeper特殊的数据结构和watcher机制,让他也能高效的实现分布式锁的功能,参考Curactor这款框架,分布式锁开箱即用。
- 元数据管理,Kafka就是使用zookeeper存储核心元数据。
- 分布式协调,zookeeper的watcher机制可以让分布式系统中的各个节点监听某个数据的变化,并且zookeeper可以把数据变化反向推送给订阅了的节点,例如kafka里面的各个broker和controller之间的协调。
- Master选举,HDFS就是用了zookeeper来保证Namenode的 HA高可用,可以保证只有一台成为主。
- zookeeper提供了全方位的分布式场景下丰富的功能,分布式协调的王者不是虚名。
- 注册中心 zookeeper可以用作dubbo的注册中心,同时也可以用作springcloud的注册中心
- zookeeper可以建立长连接
- zookeeper在分布式服务注册中心当中遵循CP原则(C:一致性;P:分区容错性)
- zookeeper一般是集群部署,单机不可能满足上面提到的这些功能的实现。我们一般都是用3-5台机器。每台机器都会在内存存储所有的元数据。划重点,zookeeper是基于内存存储的,这已经决定了他能实现高吞吐高性能
Zookeeper的文件系统:
zookeeper的内部结构类似于Linux的文件系统,都是树形结构,区别在于Zookeeper中没有目录和文件的区别,统一称为zookeeper、znode,也称为节点。
zookeeper的树形结构
zookeeper树znode的节点类型:
- 持久性(PERSISTENT ):客户端断开依旧保留
- 临时性(EPHEMERAL):客户端断开即删除,而且不可以拥有子节点
- 持久顺序性(PERSISTENT_SEQUENTIAL):客户端断开依旧保留,顺序自动编号持久化节点,这种节点会根据当前已存在的节点数自动加 1
- 临时顺序性(EPHEMERAL_SEQUENTIAL):客户端断开即删除,临时自动编号节点
顺序型节点由zookeeper维护,单向顺序不断递增
监听器:
zookeeper不光有Znode节点,同时还针对zonde做出了监听器,使用这个机制,我们可以实现分布式锁。
点击查看:常见的分布式锁
常见的监听场景:
- 监听Znode节点的数据变化
- 监听子节点的增减变化
客户端在zookeeper上监听某个zonde节点:
- 判断znode是否存在
- 检测znode数据是否有变化
- 检测znode子节点是否有变化
监听机制:
在ZooKeeper中,所有的读操作(getData,getChildren和exists)都可以设置监听。监听在某些场景下是非常有用的,当你关注某些数据的变化时,如果没有监听,你就只能不断的轮询查看数据是否发生了改变,而监听则可以避免轮询带来的开销。
设置监听:
ZooKeeper的监听事件仅触发一次,监听事件异步通知客户端,并支持多种监听方式。
仅触发一次:
当数据改变时,一个监听事件被发送到客户端,并取消监听,除非客户端再次设置监听,否则不再监听。
如果你调用了getData(“/znode1”, true)方法,第二个参数true表示设置监听,后续如果/znode1发生了改变或删除,客户端将收到监听消息。而如果/znode1再次发生改变,除非客户端执行了另一个设置监听的get操作,否则不会再收到监听消息。
应用使用ZooKeeper的监听功能的通常方式为:
- 客户端对特定对象设置监听;
- 特定对象发生变化,服务端发送监听消息到客户端,并取消监听;
- 客户端收到监听消息,发起查询,并根据需要决定是否再次监听。
ZooKeeper保证查询和监听是一个原子操作,客户端查询数据之后的所有数据变化都能收到监听。
发送到客户端:
要求操作必须成功返回到发起操作的客户端后,才能发送通知消息。监听被异步发送给监听者。ZooKeeper提供了顺序的保证:一个设置了监听的客户端在收到监听事件之前不会看到数据变化。
监听方式:
这涉及到数据改变的不同方式,ZooKeeper服务端维护了两个监听队列:数据监听队列和孩子监听队列。getData()和exists()设置数据监听,getChildren()设置孩子监听。setData()将触发数据监听,create()将触发一个节点被创建的数据监听和孩子变化的孩子监听,delete()同样将触发一个数据监听和孩子监听。
监听信息在ZooKeeper的服务端维护,是一个轻量级操作。当一个客户端连接到一个新服务端时,监听将被触发。在客户端与服务端断开连接后,监听将不能发送到客户端,当客户端重连后,任何先前的注册监听将自动重新注册并根据情况触发,整个过程自动完成。
存在一种情况将出现监听事件丢失:当客户端与服务端断开连接期间,一个被监听的节点创建并且被删除,客户端将收不到任何监听事件。
ZooKeeper服务端的监听列表仅保存在内存中,不做持久化。当一个客户端与服务端断开连接后,它所有的watch都会从内存中移除,客户端会在重连后自动重新注册它的所有watch。
监听事件:
ZooKeeper提供了以下几种事件类型,下面描述了监听这些事件的方法:
- Created event:调用exists方法设置监听;
- Deleted event:调用exists、getData、getChildren设置监听;
- Changed event:调用getData设置监听;
- Child event:调用getChildren设置监听
取消监听:
客户端能够取消监听,即使连接断开,客户端仍然能够通过设置本地标志来取消监听,取消监听成功后将收到以下事件:
- Child Remove event:取消getChildren调用注册的监听成功;
- Data Remove event:取消exists和getData调用注册的监听成功。
ZooKeeper对监听提供的保障
1. 监听是有序的,ZooKeeper客户端库确保事件、监听和异步应答的按序分发;
2. 客户端在看到一个节点的新数据之前,将先看到该节点的监听事件;
3. ZooKeeper的监听事件的顺序和ZooKeeper服务查看到的更新的顺序是一致的。
zookeeper分布式通知与协调。
1、分布式环境中,一个服务经常需要知道他的子服务状态,
1.1 namenode需知道各个DataNode的状态。
1.2 resource manager需要知道nodemanager状态
2、zookeeper实现心跳监测机制,实时信息推送,相当于一个发布/订阅系统。
Zookeeper实现分布式锁的大致思路:
系统ABC同时去访问一个节点,并且创建临时顺序节点,访问时判断自己创建的是不是最小的那个节点。
如果是,则拿到锁。
释放锁:执行完操作后,把创建的节点给删掉
如果不是,则监听比自己要小1的节点变化
举个例子:
- 系统A拿到/znode节点下的所有子节点,经过比较,发现自己(id_000000),是所有子节点最小的。所以得到锁
- 系统B拿到/znode节点下的所有子节点,经过比较,发现自己(id_000001),不是所有子节点最小的。所以监听比自己小1的节点id_000000的状态
- 系统C拿到/znode节点下的所有子节点,经过比较,发现自己(id_000002),不是所有子节点最小的。所以监听比自己小1的节点id_000001的状态
- ……
- 等到系统A执行完操作以后,将自己创建的节点删除(id_000000)。通过监听,系统B发现id_000000节点已经删除了,发现自己已经是最小的节点了,于是顺利拿到锁
- ….系统C如上
集群
配置多个实例共同构成一个集群对外提供服务以达到水平扩展的目的,每个服务器上的数据是相同的,每一个服务器均可以对外提供读和写的服务,这点和redis是相同的,即对客户端来讲每个服务器都是平等的。
zookeeper 三种部署模式:
- 单机模式:单台服务器
- 集群模式:多台服务器
- 伪集群模式:一台服务器 部署多个Zookeeper服务
Zookeeper集群是一个主从复制结构,只有高一致性、高可用和协同系统。
zookeeper三种角色:
- leader 领导者
- follower追随者
- observer观察者
Zookeeper集群中节点个数一般为奇数个(>=3),若集群中Master挂掉,剩余节点个数在半数以上时,就可以推举新的主节点,继续对外提供服务。
zookeeper选举
-
Serverid:服务器ID
比如有三台服务器,编号分别是1,2,3。
编号越大在选择算法中的权重越大。 -
Zxid:数据ID
服务器中存放的最大数据ID.
值越大说明数据越新,在选举算法中数据越新权重越大。 -
Epoch:逻辑时钟
或者叫投票的次数,同一轮投票过程中的逻辑时钟值是相同的。每投完一次票这个数据就会增加,然后与接收到的其它服务器返回的投票信息中的数值相比,根据不同的值做出不同的判断。 -
Server状态:选举状态
- LOOKING,竞选状态。 - FOLLOWING,随从状态,同步leader状态,参与投票。 - OBSERVING,观察状态,同步leader状态,不参与投票。 - LEADING,领导者状态。
选举过程:
ZAB协议:
ZAB协议是zookeeper为分布式协调服务设计的一种支持容错、崩溃、恢复的原子广播协议,是zookeeper保证数据一致性的核心算法。
- ZAB协议需要确保那些已经在leader服务器上提交的事务最终被所有的服务器提交
- ZAB协议需要确保丢弃那些只在leader上被提出而没有被提交的事务
- zookeeper follower server 收到client的写请求
- 转发给Leader处理
- Leader节点先将请求数据持久化到本地
- 然后将此次更新的数据(propose)更新提议给Follower
- Follower节点接收到请求,成功的将修改本地持久化,发送ack给Leader
- Leader接收到半数以上的ACK回复是,Leader将广播commit消息并在本地提交改消息
- 当收到Leader发来的Commit消息时,Follower提交改消息
Zookeeper数据同步机制:
- zookeeper集群数据同步的核心是原子广播,这个机制保证了各个server之间数据同步的一致性
- 来自client的读请求,直接由server的本地副本来进行服务的
- 来自client的写请求,如果是follower节点直接转发给leader进行处理,然后通过广播来保证各个节点都一致
每当我们进入一个写请求或者leader挂了,就是触发zab协议进行选举或者广播同步。
zookeeper分布式锁。
1、zookeeper是强一致性的
2、实现锁的独占性。
3、控制锁的时序。
分布式队列
分布式队列有两种
1、当一个队列全部都聚齐时,这个队列才可以用,否则这个队列会一直等所有成员到达,这种成为同步队列。
1.1 当一个job由所有的task组成时,所有的任务完成后,job才运行。
1.2可为job创建一个/job,然后在该目录下,为每个完成task创建一个临时的znode,当临时节点的目录数达到task总数时,则job表示完成。
2、队列实现FIFO模式,实现生产者和消费者模型。
API命令:
- ls / lsz path:列出当前目录下的全部子目录,lsz会多包含一些状态信息
- create path data:创建持久znode,并存放数据data
- create -e path data:创建临时znode,并存放数据data
- create -s -e path data:在znode下创建临时顺序节点
- get path:获取znode存储的数据
- set path data [version]:给znode赋值
- delete path [version]:删除znode
- stat path watch:注册监听znode,如果znode删除,创建通知
- get path watch:注册监听znode保存的数据变化
- ls path watch:注册监听znode的子节点的变化、包括新增和和删除
==== END ====
至此,以上是我在学习zookeeper过程中一个入门的了解,当然zookeeper远比我们这里描述的功能多,如果您在阅读过程中发现有什么错误的地方,还请留言相告,我会及时作出修正。