年度大作《我想进大厂》之Zookeeper面试真题,有了它妈妈再
前言
我也不知道该写些什么了,算了,直接进去正文吧!
由于资料内容太多,平台篇幅限制,小编就展现了以上部分面试专题与资料,如需获取以下全部面试资料,可以【点击这里】,可复制链接后用石墨文档 App 或小程序打开获取。
正文
问题一:ZooKeeper 是什么?
ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby
一个开源的实现,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
客户端的读请求可以被集群中的任意一台机器处理,如果读请求在节点上注册了监听器,这个监听器也是由所连接的 zookeeper 机器来处理。对于写请求,这些请求会同时发给其他 zookeeper 机器并且达成一致后,请求才会返回成功。因此,随着 zookeeper 的集群机器增多,读请求的吞吐会提高但是写请求的吞吐会下降。有序性是 zookeeper 中非常重要的一个特性,所有的更新都是全局有序的,每个更新都有一个唯一的时间戳,这个时间戳称为 zxid(Zookeeper Transaction Id)
。而读请求只会相对于更新有序,也就是读请求的返回结果中会带有这个 zookeeper
最新的 zxid
。
问题二:四种类型的 znode
-
PERSISTENT
-持久化目录节点
客户端与zookeeper
断开连接后,该节点依旧存在 -
PERSISTENT_SEQUENTIAL
-持久化顺序编号目录节点
客户端与 zookeeper 断开连接后,该节点依旧存在,只是 Zookeeper 给该节点名称进行顺序编号 -
EPHEMERAL
-临时目录节点
客户端与 zookeeper 断开连接后,该节点被删除 -
EPHEMERAL_SEQUENTIAL
-临时顺序编号目录节点
客户端与 zookeeper 断开连接后,该节点被删除,只是 Zookeeper 给该节点名称进行顺序编号
问题三:Zookeeper 做了什么?
- 命名服务
- 配置管理
- 集群管理
- 分布式锁
- 队列管理
问题四:Zookeeper 集群管理(文件系统、通知机制)
所谓集群管理无在乎两点:是否有机器退出和加入、选举 master。
对于第一点,所有机器约定在父目录下创建临时目录节点,然后监听父目录节点的子节点变化消息。一旦有机器挂掉,该机器与 zookeeper 的连接断开,其所创建的临时目录节点被删除,所有其他机器都收到通知:某个兄弟目录被删除,于是,所有人都知道:它上船了。
新机器加入也是类似,所有机器收到通知:新兄弟目录加入,highcount
又有了,对于第二点,我们稍微改变一下,所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为 master
就好。
问题五:获取分布式锁的流程
Zookeeper面试真题在获取分布式锁的时候在 locker 节点 下创建临时顺序节点,释放锁的时候删除该临时节点。客户端调用 createNode 方法 在 locker
下创建临时顺序节点,然后调用 getChildren(“locker”)
来获取 locker
下面的所有子节点,注意此时不用设置任何 Watcher
。客户端获取到所有的子节点 path
之后,如果发现自己创建的节点在所有创建的子节点序号最小,那么就认为该客户端获取到了锁。如果发现自己创建的节点并非 locker
所有子节点中最小的,说明自己还没有获取到锁,此时客户端需要找到比自己小的那个节点,然后对其调用 exist()方法
,同时对其注册事件监听器。之后,让这个被关注的节点删除,则客户端的 Watcher
会收到相应通知,此时再次判断自己创建的节点是否是 locker 子节点
中序号最小的,如果是则获取到了锁,如果不是则重复以上步骤继续获取到比自己小的一个节点并注册监听。当前这个过程中还需要许多的逻辑判断。
代码的实现主要是基于互斥锁,获取分布式锁的重点逻辑在于 BaseDistributedLock
,实现了基于 Zookeeper 实现分布式锁的细节。
问题六:Zookeeper 队列管理(文件系统、通知机制)
两种类型的队列:
- 同步队列,当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达。
- 队列按照
FIFO
方式进行入队和出队操作。
第一类,在约定目录下创建临时目录节点,监听节点数目是否是我们要求的数目。
第二类,和分布式锁服务中的控制时序场景基本原理一致,入列有编号,出列按编号。在特定的目录下创建 PERSISTENT_SEQUENTIAL 节点
,创建成功时 Watcher
通知等待的队列,队列删除序列号最小的节点用以消费。此场景下 Zookeeper 的 znode
用于消息存储,znode
存储的数据就是消息队列中的消息内容,SEQUENTIAL 序列号
就是消息的编号,按序取出即可。由于创建的节点是持久化的,所以不必担心队列消息的丢失问题。
问题七:Zookeeper 数据复制
Zookeeper 作为一个集群提供一致的数据服务,自然,它要在所有机器间做数据复制。数据复制的好处:
- 容错:一个节点出错,不致于让整个系统停止工作,别的节点可以接管它的工作;
- 提高系统的扩展能力 :把负载分布到多个节点上,或者增加节点来提高系统的负载能力;
- 提高性能:让客户端本地访问就近的节点,提高用户访问速度。
从客户端读写访问的透明度来看,数据复制集群系统分下面两种:
- 写主(WriteMaster) :对数据的修改提交给指定的节点。读无此限制,可以读取任何一个节点。这种情况下客户端需要对读与写进行区别,俗称读写分离;
- 写任意(Write Any):对数据的修改可提交给任意的节点,跟读一样。这种情况下,客户端对集群节点的角色与变化透明。
对 zookeeper 来说,它采用的方式是写任意。通过增加机器,它的读吞吐能力和响应能力扩展性非常好,而写,随着机器的增多吞吐能力肯定下降(这也是它建立 observer
的原因),而响应能力则取决于具体实现方式,是延迟复制保持最终一致性,还是立即复制快速响应。
问题八:Zookeeper 下 Server 工作状态
每个 Server
在工作过程中有三种状态:
- LOOKING:当前 Server 不知道 leader 是谁,正在搜寻
- LEADING:当前 Server 即为选举出来的 leader
- FOLLOWING:leader 已经选举出来,当前 Server 与之同步
问题九:zk 节点宕机如何处理?
Zookeeper 本身也是集群,推荐配置不少于 3 个服务器。Zookeeper 自身也要保证当一个节点宕机时,其他节点会继续提供服务。
如果是一个 Follower
宕机,还有 2 台服务器提供访问,因为 Zookeeper 上的数据是有多个副本的,数据并不会丢失;
如果是一个 Leader
宕机,Zookeeper 会选举出新的 Leader
。
ZK 集群的机制是只要超过半数的节点正常,集群就能正常提供服务。只有在 ZK 节点挂得太多,只剩一半或不到一半节点能工作,集群才失效。
所以
3 个节点的 cluster
可以挂掉 1 个节点(leader 可以得到 2 票>1.5)
2 个节点的 cluster
就不能挂掉任何 1 个节点了(leader 可以得到 1 票<=1)
问题十:zookeeper watch 机制
Watch 机制官方声明:一个 Watch 事件是一个一次性的触发器,当被设置了 Watch 的数据发生了改变的时候,则服务器将这个改变发送给设置了 Watch 的客户端,以便通知它们。
Zookeeper 机制的特点:
- 一次性触发数据发生改变时,一个
watcher event
会被发送到client
,但是client
只会收到一次这样的信息。 -
watcher event
异步发送watcher
的通知事件从server
发送到client
是异步的,这就存在一个问题,不同的客户端和服务器之间通过socket
进行通信,由于网络延迟或其他因素导致客户端在不通的时刻监听到事件,由于 Zookeeper 本身提供了ordering guarantee
,即客户端监听事件后,才会感知它所监视znode
发生了变化。所以我们使用 Zookeeper 不能期望能够监控到节点每次的变化。Zookeeper 只能保证最终的一致性,而无法保证强一致性。 - 数据监视 Zookeeper 有数据监视和子数据监视
getdata() and exists()
设置数据监视,getchildren()
设置了子节点监视。 - 注册
watcher getData
、exists
、getChildren
- 触发
watcher create
、delete
、setData
-
setData()
会触发znode
上设置的data watch
(如果 set 成功的话)。一个成功的create()
操作会触发被创建的znode
上的数据watch
,以及其父节点上的child watch
。而一个成功的delete()
操作将会同时触发一个znode
的data watch
和child watch
(因为这样就没有子节点了),同时也会触发其父节点的child watch
。 - 当一个客户端连接到一个新的服务器上时,
watch
将会被以任意会话事件触发。当与一个服务器失去连接的时候,是无法接收到watch
的。而当client
重新连接时,如果需要的话,所有先前注册过的watch
,都会被重新注册。通常这是完全透明的。只有在一个特殊情况下,watch
可能会丢失:对于一个未创建的znode
的exist watch
,如果在客户端断开连接期间被创建了,并且随后在客户端连接上之前又删除了,这种情况下,这个watch
事件可能会被丢失。 -
Watch
是轻量级的,其实就是本地 JVM 的Callback
,服务器端只是存了是否有设置了Watcher
的布尔类型
写在最后
由于资料内容太多,平台篇幅限制,小编就展现了以上部分面试专题与资料,如需获取以下全部面试资料,可以【点击这里】,可复制链接后用石墨文档 App 或小程序打开获取。
记得点赞、关注哦!!!