关于后端:Zookeeper面试常见11个连环炮

37次阅读

共计 8926 个字符,预计需要花费 23 分钟才能阅读完成。

获取:10 万字的面试小抄

面试的时候,面试官只有看到你简历的上写的有 Zookeeper(相熟、把握)之类,那你至多要筹备接下来的 11 连问。

NO1:说说 zookeeper 是什么?

ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现(Chubby 是不开源的),它是集群的管理者,监督着集群中各个节点的状态依据节点提交的反馈进行下一步正当操作。最终,将简略易用的接口和性能高效、性能稳固的零碎提供给用户。

Zookeeper 一个最罕用的应用场景就是用于负责服务生产者和服务消费者的注册核心,服务生产者将本人提供的服务注册到 Zookeeper 核心,服务的消费者在进行服务调用的时候先到 Zookeeper 中查找服务,获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据,简略示例图如下:

NO2:理解 Zookeeper 的零碎架构吗?

ZooKeeper 的架构图中咱们须要理解和把握的次要有:

(1)ZooKeeper 分为服务器端(Server)和客户端(Client),客户端能够连贯到整个 ZooKeeper 服务的任意服务器上(除非 leaderServes 参数被显式设置,leader 不容许承受客户端连贯)。

(2)客户端应用并保护一个 TCP 连贯,通过这个连贯发送申请、承受响应、获取察看的事件以及发送心跳。如果这个 TCP 连贯中断,客户端将主动尝试连贯到另外的 ZooKeeper 服务器。客户端第一次连贯到 ZooKeeper 服务时,承受这个连贯的 ZooKeeper 服务器会为这个客户端建设一个会话。当这个客户端连贯到另外的服务器时,这个会话会被新的服务器从新建设。

(3)上图中每一个 Server 代表一个装置 Zookeeper 服务的机器,即是整个提供 Zookeeper 服务的集群(或者是由伪集群组成);

(4)组成 ZooKeeper 服务的服务器必须彼此理解。它们保护一个内存中的状态图像,以及长久存储中的事务日志和快照,只有大多数服务器可用,ZooKeeper 服务就可用;

(5)ZooKeeper 启动时,将从实例中选举一个 leader,Leader 负责解决数据更新等操作,一个更新操作胜利的标记是当且仅当大多数 Server 在内存中胜利批改数据。每个 Server 在内存中存储了一份数据。

(6)Zookeeper 是能够集群复制的,集群间通过 Zab 协定(Zookeeper Atomic Broadcast)来保持数据的一致性;

(7)Zab 协定蕴含两个阶段:leader election 阶段和 Atomic Brodcast 阶段。

  • a) 集群中将选举出一个 leader,其余的机器则称为 follower,所有的写操作都被传送给 leader,并通过 brodcast 将所有的更新通知给 follower。
  • b) 当 leader 解体或者 leader 失去大多数的 follower 时,须要从新选举出一个新的 leader,让所有的服务器都复原到一个正确的状态。
  • c) 当 leader 被选举进去,且大多数服务器实现了 和 leader 的状态同步后,leadder election 的过程就完结了,就将会进入到 Atomic brodcast 的过程。
  • d) Atomic Brodcast 同步 leader 和 follower 之间的信息,保障 leader 和 follower 具备形同的零碎状态。

NO3:能说说 Zookeeper 的工作原理?

Zookeeper 的外围是原子播送,这个机制保障了各个 Server 之间的同步。实现这个机制的协定叫做 Zab 协定。

Zab 协定有两种模式,它们 别离是恢复模式(选主)和播送模式(同步)。

Zab 协定 的全称是 Zookeeper Atomic Broadcast**(Zookeeper 原子播送)。Zookeeper 是通过 Zab 协定来保障分布式事务的最终一致性。Zab 协定要求每个 Leader 都要经验三个阶段:发现,同步,播送。

当服务启动或者在领导者解体后,Zab 就进入了恢复模式,当领导者被选举进去,且大多数 Server 实现了和 leader 的状态同步当前,恢复模式就完结了。状态同步保障了 leader 和 Server 具备雷同的零碎状态。

为了保障事务的程序一致性,zookeeper 采纳了递增的事务 id 号(zxid)来标识事务。所有的提议(proposal)都在被提出的时候加 上了 zxid。实现中 zxid 是一个 64 位的数字,它高 32 位是 epoch 用来标识 leader 关系是否扭转,每次一个 leader 被选出来,它都会有一 个新的 epoch,标识以后属于那个 leader 的统治期间。低 32 位用于递增计数。

epoch:能够了解为皇帝的年号,当新的皇帝 leader 产生后,将有一个新的 epoch 年号。

每个 Server 在工作过程中有三种状态:

  • LOOKING:以后 Server 不晓得 leader 是谁,正在搜查。
  • LEADING:以后 Server 即为选举进去的 leader。
  • FOLLOWING:leader 曾经选举进去,以后 Server 与之同步。

NO4:Zookeeper 为什么要这么设计?

ZooKeeper 设计的目标是提供高性能、高可用、程序一致性的分布式协调服务、保证数据最终一致性。

高性能(简略的数据模型)

  1. 采纳树形构造组织数据节点;
  2. 全量数据节点,都存储在内存中;
  3. Follower 和 Observer 间接解决非事务申请;

高可用(构建集群)

  1. 半数以上机器存活,服务就能失常运行
  2. 主动进行 Leader 选举

程序一致性(事务操作的程序)

  1. 每个事务申请,都会转发给 Leader 解决
  2. 每个事务,会调配全局惟一的递增 id(zxid,64 位:epoch + 自增 id)

最终一致性

  1. 通过提议投票形式,保障事务提交的可靠性
  2. 提议投票形式,只能保障 Client 收到事务提交胜利后,半数以上节点可能看到最新数据

NO5:你晓得 Zookeeper 中有哪些角色?

零碎模型:

领导者(leader)

Leader 服务器为客户端提供读服务和写服务。负责进行投票的发动和决定,更新零碎状态。

学习者(learner)

  • 跟随者(follower)Follower 服务器为客户端提供读服务,参加 Leader 选举过程,参加写操作“过半写胜利”策略。
  • 观察者(observer)Observer 服务器为客户端提供读服务,不参加 Leader 选举过程,不参加写操作“过半写胜利”策略。用于在不影响写性能的前提下晋升集群的读性能。

客户端(client):服务申请发起方。

NO6:你相熟 Zookeeper 节点 ZNode 和相干属性吗?

节点有哪些类型?

Znode 两种类型

长久的(persistent):客户端和服务器端断开连接后,创立的节点不删除(默认)。

短暂的(ephemeral):客户端和服务器端断开连接后,创立的节点本人删除。

Znode 有四种模式

  • 长久化目录节点(PERSISTENT):客户端与 Zookeeper 断开连接后,该节点仍旧存在长久化程序编号目录节点(PERSISTENT_SEQUENTIAL)
  • 客户端与 Zookeeper 断开连接后,该节点仍旧存在,只是 Zookeeper 给该节点名称进行程序编号:长期目录节点(EPHEMERAL)
  • 客户端与 Zookeeper 断开连接后,该节点被删除:长期程序编号目录节点(EPHEMERAL_SEQUENTIAL)
  • 客户端与 Zookeeper 断开连接后,该节点被删除,只是 Zookeeper 给该节点名称进行程序编号

「留神」:创立 ZNode 时设置程序标识,ZNode 名称后会附加一个值,顺序号是一个枯燥递增的计数器,由父节点保护。

节点属性有哪些

一个 znode 节点不仅能够存储数据,还有一些其余特地的属性。接下来咱们创立一个 /test 节点剖析一下它各个属性的含意。

 [zk: localhost:2181(CONNECTED) 6] get /test
    456
    cZxid = 0x59ac //
    ctime = Mon Mar 30 15:20:08 CST 2020
    mZxid = 0x59ad
    mtime = Mon Mar 30 15:22:25 CST 2020
    pZxid = 0x59ac
    cversion = 0
    dataVersion = 2
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 3
    numChildren = 0 

属性阐明

NO7:请简述 Zookeeper 的选主流程

Zookeeper 的外围是原子播送,这个机制保障了各个 Server 之间的同步。实现这个机制的协定叫做 Zab 协定。Zab 协定有两种模式,它们别离是恢复模式(选主)和播送模式(同步)。当服务启动或者在领导者解体后,Zab 就进入了恢复模式,当领导者被选举进去,且大多数 Server 实现了和 leader 的状态同步当前,恢复模式就完结了。状态同步保障了 leader 和 Server 具备雷同的零碎状态。leader 选举是保障分布式数据一致性的要害。

呈现选举次要是两种场景:初始化、leader 不可用。

当 zk 集群中的一台服务器呈现以下两种状况之一时,就会开始 leader 选举。

(1)服务器初始化启动。

(2)服务器运行期间无奈和 leader 放弃连贯。

而当一台机器进入 leader 选举流程时,以后集群也可能处于以下两种状态。

(1)集群中原本就曾经存在一个 leader。

(2)集群中的确不存在 leader。

首先第一种状况,通常是集群中某一台机器启动比拟晚,在它启动之前,集群曾经失常工作,即曾经存在一台 leader 服务器。当该机器试图去选举 leader 时,会被告知以后服务器的 leader 信息,它仅仅须要和 leader 机器建设连贯,并进行状态同步即可。

重点是 leader 不可用了,此时的选主制度。

投票信息中蕴含两个最根本的信息。

sid:即 server id,用来标识该机器在集群中的机器序号。

zxid:即 zookeeper 事务 id 号。

ZooKeeper 状态的每一次扭转, 都对应着一个递增的 Transaction id,,该 id 称为 zxid.,因为 zxid 的递增性质, 如果 zxid1 小于 zxid2,,那么 zxid1 必定先于 zxid2 产生。创立任意节点,或者更新任意节点的数据,或者删除任意节点,都会导致 Zookeeper 状态产生扭转,从而导致 zxid 的值减少。

以(sid,zxid)的模式来标识一次投票信息。

例如:如果以后服务器要推举 sid 为 1,zxid 为 8 的服务器成为 leader,那么投票信息能够示意为(1,8)

集群中的每台机器收回本人的投票后,也会承受来自集群中其余机器的投票。每台机器都会依据肯定的规定,来解决收到的其余机器的投票,以此来决定是否须要变更本人的投票。

规定如下

(1)初始阶段,都会给本人投票。

(2)当接管到来自其余服务器的投票时,都须要将他人的投票和本人的投票进行 pk,规定如下:

优先查看 zxid。zxid 比拟大的服务器优先作为 leader。如果 zxid 雷同的话,就比拟 sid,sid 比拟大的服务器作为 leader。

NO8:有理解过 watch 机制吗?

简略地说:client 端会对某个 znode 注册一个 watcher 事件,当该 znode 发生变化时,这些 client 会收到 ZooKeeper 的告诉,而后 client 能够依据 znode 变动来做出业务上的扭转等。

经典应用场景:zookeeper 为 dubbo 提供服务的注册与发现,作为注册核心,然而大家有没有想过 zookeeper 为啥可能实现服务的注册与发现吗?

这就不得不说一下 zookeeper 的灵魂 Watcher(监听者)。

什么是 watcher?

watcher 是 zooKeeper 中一个十分外围性能,客户端 watcher 能够监控节点的数据变动以及它子节点的变动,一旦这些状态发生变化,zooKeeper 服务端就会告诉所有在这个节点上设置过 watcher 的客户端,从而每个客户端都很快感知,它所监听的节点状态发生变化,而做出对应的逻辑解决。

简略的介绍了一下 watcher,那么咱们来剖析一下,zookeeper 是如何实现服务的注册与发现。zookeeper 的服务注册与发现,次要利用的是 zookeeper 的 znode 节点数据模型和 watcher 机制,大抵的流程如下:

  • 服务注册:服务提供者(Provider)启动时,会向 zookeeper 服务端注册服务信息,也就是创立一个节点,例如:用户注册服务 com.xxx.user.register,并在节点上存储服务的相干数据(如服务提供者的 ip 地址、端口等)。
  • 服务发现:服务消费者(Consumer)启动时,依据本身配置的依赖服务信息,向 zookeeper 服务端获取注册的服务信息并设置 watch 监听,获取到注册的服务信息之后,将服务提供者的信息缓存在本地,并进行服务的调用。
  • 服务告诉:一旦服务提供者因某种原因宕机不再提供服务之后,客户端与 zookeeper 服务端断开连接,zookeeper 服务端上服务提供者对应服务节点会被删除(例如:用户注册服务 com.xxx.user.register),随后 zookeeper 服务端会异步向所有生产用户注册服务 com.xxx.user.register,且设置了 watch 监听的服务消费者收回节点被删除的告诉,消费者依据收到的告诉拉取最新服务列表,更新本地缓存的服务列表。

上边的过程就是 zookeeper 能够实现服务注册与发现的大抵原理。

watcher 有哪些类型?

znode 节点能够设置两类 watch,一种是 DataWatches,基于 znode 节点的数据变更从而触发 watch 事件,触发条件 getData()、exists()、setData()、create()。

另一种是 Child Watches,基于 znode 的孩子节点产生变更触发的 watch 事件,触发条件 getChildren()、create()。

而在调用 delete() 办法删除 znode 时,则会同时触发 Data Watches 和 Child Watches,如果被删除的节点还有父节点,则父节点会触发一个 Child Watches。

watcher 有什么个性?

watch 对节点的监听事件是一次性的!客户端在指定的节点设置了监听 watch,一旦该节点数据产生变更告诉一次客户端后,客户端对该节点的监听事件就生效了。

如果还要持续监听这个节点,就须要咱们在客户端的监听回调中,再次对节点的监听 watch 事件设置为 True。否则客户端只能接管到一次该节点的变更告诉。

NO9:那你说说 Zookeeper 有哪些利用场景?

数据公布与订阅

公布与订阅即所谓的配置管理,顾名思义就是将数据公布到 ZooKeeper 节点上,供订阅者动静获取数据,实现配置信息的集中式治理和动静更新。例如全局的配置信息,地址列表等就非常适合应用。

数据公布 / 订阅的一个常见的场景是配置核心,发布者把数据公布到 ZooKeeper 的一个或一系列的节点上,供订阅者进行数据订阅,达到动静获取数据的目标。

配置信息个别有几个特点:

  1. 数据量小的 KV
  2. 数据内容在运行时会产生动态变化
  3. 集群机器共享,配置统一

ZooKeeper 采纳的是推拉联合的形式。

  1. 推: 服务端会推给注册了监控节点的客户端 Wathcer 事件告诉
  2. 拉: 客户端取得告诉后,而后被动到服务端拉取最新的数据
命名服务

作为分布式命名服务,命名服务是指通过指定的名字来获取资源或者服务的地址,利用 ZooKeeper 创立一个全局的门路,这个门路就能够作为一个名字,指向集群中的集群,提供的服务的地址,或者一个近程的对象等等。

对立命名服务的命名结构图如下所示:

1、在分布式环境下,常常须要对利用 / 服务进行对立命名,便于辨认不同服务。

  • 相似于域名与 IP 之间对应关系,IP 不容易记住,而域名容易记住。
  • 通过名称来获取资源或服务的地址,提供者等信息。

2、依照层次结构组织服务 / 利用名称。

  • 可将服务名称以及地址信息写到 ZooKeeper 上,客户端通过 ZooKeeper 获取可用服务列表类。
配置管理

程序分布式的部署在不同的机器上,将程序的配置信息放在 ZooKeeper 的 znode 下,当有配置产生扭转时,也就是 znode 发生变化时,能够通过扭转 zk 中某个目录节点的内容,利用 watch 告诉给各个客户端 从而更改配置。

ZooKeeper 配置管理结构图如下所示:

1、分布式环境下,配置文件治理和同步是一个常见问题。

  • 一个集群中,所有节点的配置信息是统一的,比方 Hadoop 集群。
  • 对配置文件批改后,心愿可能疾速同步到各个节点上。

2、配置管理可交由 ZooKeeper 实现。

  • 可将配置信息写入 ZooKeeper 上的一个 Znode。
  • 各个节点监听这个 Znode。
  • 一旦 Znode 中的数据被批改,ZooKeeper 将告诉各个节点。
集群治理

所谓集群治理就是:是否有机器退出和退出、选举 master。

集群治理次要指集群监控和集群管制两个方面。前者侧重于集群运行时的状态的收集,后者则是对集群进行操作与管制。开发和运维中,面对集群,常常有如下需要:

  1. 心愿晓得集群中到底有多少机器在工作
  2. 对集群中的每台机器的运行时状态进行数据收集
  3. 对集群中机器进行高低线的操作

集群治理结构图如下所示:

1、分布式环境中,实时把握每个节点的状态是必要的,可依据节点实时状态做出一些调整。

2、可交由 ZooKeeper 实现。

  • 可将节点信息写入 ZooKeeper 上的一个 Znode。
  • 监听这个 Znode 可获取它的实时状态变动。

3、典型利用

  • Hbase 中 Master 状态监控与选举。

利用 ZooKeeper 的强一致性,可能保障在分布式高并发状况下节点创立的全局唯一性,即:同时有多个客户端申请创立 /currentMaster 节点,最终肯定只有一个客户端申请可能创立胜利

分布式告诉与协调

1、分布式环境中,常常存在一个服务须要晓得它所治理的子服务的状态。

a)NameNode 需晓得各个 Datanode 的状态。

b)JobTracker 需晓得各个 TaskTracker 的状态。

2、心跳检测机制可通过 ZooKeeper 来实现。

3、信息推送可由 ZooKeeper 来实现,ZooKeeper 相当于一个公布 / 订阅零碎。

分布式锁

处于不同节点上不同的服务,它们可能须要程序的拜访一些资源,这里须要一把分布式的锁。

分布式锁具备以下个性:写锁、读锁、时序锁。

写锁:在 zk 上创立的一个长期的无编号的节点。因为是无序编号,在创立时不会主动编号,导致只能客户端有一个客户端失去锁,而后进行写入。

读锁:在 zk 上创立一个长期的有编号的节点,这样即便下次有客户端退出是同时创立雷同的节点时,他也会主动编号,也能够取得锁对象,而后对其进行读取。

时序锁:在 zk 上创立的一个长期的有编号的节点依据编号的大小管制锁。

分布式队列

分布式队列分为两种:

1、当一个队列的成员都聚齐时,这个队列才可用,否则始终期待所有成员达到,这种是同步队列。

a)一个 job 由多个 task 组成,只有所有工作实现后,job 才运行实现。

b)可为 job 创立一个 /job 目录,而后在该目录下,为每个实现的 task 创立一个长期的 Znode,一旦长期节点数目达到 task 总数,则表明 job 运行实现。

2、队列依照 FIFO 形式进行入队和出队操作,例如实现生产者和消费者模型。

NO10:晓得监听器的原理吗?

  1. 创立一个 Main()线程。
  2. 在 Main()线程中创立两个线程,一个负责网络连接通信(connect),一个负责监听(listener)。
  3. 通过 connect 线程将注册的监听事件发送给 Zookeeper。
  4. 将注册的监听事件增加到 Zookeeper 的注册监听器列表中。
  5. Zookeeper 监听到有数据或门路发生变化时,把这条音讯发送给 Listener 线程。
  6. Listener 线程外部调用 process()办法。

NO11:为什么 Zookeeper 集群的数目,个别为奇数个?

首先须要明确 zookeeper 选举的规定:leader 选举,要求 可用节点数量 > 总节点数量 /2

比方:标记一个写是否胜利是要在超过一半节点发送写申请胜利时才认为无效。同样,Zookeeper 抉择领导者节点也是在超过一半节点批准时才无效。最初,Zookeeper 是否失常是要依据是否超过一半的节点失常才算失常。这是基于 CAP 的一致性原理。

zookeeper 有这样一个个性:集群中只有有过半的机器是失常工作的,那么整个集群对外就是可用的。

也就是说如果有 2 个 zookeeper,那么只有有 1 个死了 zookeeper 就不能用了,因为 1 没有过半,所以 2 个 zookeeper 的死亡容忍度为 0;

同理,要是有 3 个 zookeeper,一个死了,还剩下 2 个失常的,过半了,所以 3 个 zookeeper 的容忍度为 1;

同理:

  • 2->0;两个 zookeeper,最多 0 个 zookeeper 能够不可用。
  • 3->1;三个 zookeeper,最多 1 个 zookeeper 能够不可用。
  • 4->1;四个 zookeeper,最多 1 个 zookeeper 能够不可用。
  • 5->2;五个 zookeeper,最多 2 个 zookeeper 能够不可用。
  • 6->2;两个 zookeeper,最多 0 个 zookeeper 能够不可用。

….

会发现一个法则,2n 和 2n- 1 的容忍度是一样的,都是 n -1,所以为了更加高效,何必减少那一个不必要的 zookeeper 呢。

zookeeper 的选举策略也是须要半数以上的节点批准能力入选 leader,如果是偶数节点可能导致票数雷同的状况。

总结

很多面试官,面试套路根本就是这个,从背景到原理,到架构体系,再到 Zookeeper 固有特点、最初要求面试者能说出 Zookeeper 的理论利用场景。

「你多学一样本事,就少说一句求人的话。」

举荐浏览

把握 Mybatis 动静映射,我可是下了功夫的

2020 所有原创

写给大忙人看的 JAVA 核心技术.pdf 下载

图解多线程

京东面试:说说 MySQL 的架构体系

正文完
 0