面试官的ZooKeeper十二连问,我已经顶不了了。

在这里插入图片描述
前段时间去面试,面试管对我进行了长达半小时的zookeeper拷问,过程非常艰辛,做为一个菜鸡的我,都没怎么回答上了,后来回家补充了一下知识把此次记下来,我是怎么回答的已经不重要了,反正都凉了,但失败仍是要总结的,我不会不表明百度不会。node

因此把这最为记忆深入的zookeeper死死记住了下来,也把知识点整理了一些,同时也整理了其余知识点,同时整理了2020年各个大厂的面试题,须要的朋友能够点击连接:点这个,点这个。 暗号:csdn。下面咱们就来看看面试管到底问了我什么。
在这里插入图片描述web

1.面试官:工做中使用过Zookeeper嘛?你知道它是什么,有什么用途呢?

我: 有使用过的,使用ZooKeeper做为dubbo的注册中心,使用ZooKeeper实现分布式锁。面试

ZooKeeper,它是一个开放源码的分布式协调服务,它是一个集群的管理者,它将简单易用的接口提供给用户。redis

能够基于Zookeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。数据库

2.面试官:说下什么是命名服务,什么是配置管理,又什么是集群管理吧?

幸亏刷过面试题,无所畏惧性能优化

命名服务就是:
命名服务是指经过指定的名字来获取资源或者服务地址。Zookeeper能够建立一个全局惟一的路径,这个路径就能够做为一个名字。被命名的实体能够是集群中的机器,服务的地址,或者是远程的对象等。一些分布式服务框架(RPC、RMI)中的服务地址列表,经过使用命名服务,客户端应用可以根据特定的名字来获取资源的实体、服务地址和提供者信息等。服务器

配置管理:
实际项目开发中,咱们常用.properties或者xml须要配置不少信息,如数据库链接信息、fps地址端口等等。由于你的程序通常是分布式部署在不一样的机器上(若是你是单机应用当我没说),若是把程序的这些配置信息保存在zk的znode节点下,当你要修改配置,即znode会发生变化时,能够经过改变zk中某个目录节点的内容,利用watcher通知给各个客户端,从而更改配置。数据结构

集群管理:
集群管理包括集群监控和集群控制,其实就是监控集群机器状态,剔除机器和加入机器。zookeeper能够方便集群机器的管理,它能够实时监控znode节点的变化,一旦发现有机器挂了,该机器就会与zk断开链接,对用的临时目录节点会被删除,其余全部机器都收到通知。新机器加入也是相似酱紫,全部机器收到通知:有新兄弟目录加入啦。架构

3.面试官:提到了znode节点,那你知道znode有几种类型呢?zookeeper的数据模型是怎样的呢?

zookeeper的数据模型并发

ZooKeeper的视图数据结构,很像Unix文件系统,也是树状的,这样能够肯定每一个路径都是惟一的。zookeeper的节点统一叫作znode,它是能够经过路径来标识,结构图以下:
在这里插入图片描述

znode的4种类型

根据节点的生命周期,znode能够分为4种类型,分别是持久节点(PERSISTENT)、持久顺序节点(PERSISTENT_SEQUENTIAL)、临时节点(EPHEMERAL)、临时顺序节点(EPHEMERAL_SEQUENTIAL)

持久节点(PERSISTENT)

这类节点被建立后,就会一直存在于Zk服务器上。直到手动删除。

持久顺序节点(PERSISTENT_SEQUENTIAL)

它的基本特性同持久节点,不一样在于增长了顺序性。父节点会维护一个自增整性数字,用于子节点的建立的前后顺序。

临时节点(EPHEMERAL)

临时节点的生命周期与客户端的会话绑定,一旦客户端会话失效(非TCP链接断开),那么这个节点就会被自动清理掉。zk规定临时节点只能做为叶子节点。

临时顺序节点(EPHEMERAL_SEQUENTIAL)

基本特性同临时节点,添加了顺序的特性。

四、面试官:你知道znode节点里面存储的是什么吗?每一个节点的数据最大不能超过多少呢?

Znode数据节点的代码以下

public class DataNode implements Record {
    byte data[];                    
    Long acl;                       
    public StatPersisted stat;       
    private Set<String> children = null; 
}

Znode包含了存储数据、访问权限、子节点引用、节点状态信息,如图:
在这里插入图片描述
data: znode存储的业务数据信息
ACL: 记录客户端对znode节点的访问权限,如IP等。
child: 当前节点的子节点引用
stat: 包含Znode节点的状态信息,好比事务id、版本号、时间戳等等。

每一个节点的数据最大不能超过多少呢

为了保证高吞吐和低延迟,以及数据的一致性,znode只适合存储很是小的数据,不能超过1M,最好都小于1K。

五、面试官:你知道znode节点上的监听机制嘛?讲下Zookeeper watch机制吧。

  • Watcher机制
  • 监听机制的工做原理
  • Watcher特性总结

Watcher监听机制

Zookeeper 容许客户端向服务端的某个Znode注册一个Watcher监听,当服务端的一些指定事件触发了这个Watcher,服务端会向指定客户端发送一个事件通知来实现分布式的通知功能,而后客户端根据 Watcher通知状态和事件类型作出业务上的改变。

能够把Watcher理解成客户端注册在某个Znode上的触发器,当这个Znode节点发生变化时(增删改查),就会触发Znode对应的注册事件,注册的客户端就会收到异步通知,而后作出业务的改变。

Watcher监听机制的工做原理
在这里插入图片描述
ZooKeeper的Watcher机制主要包括客户端线程、客户端 WatcherManager、Zookeeper服务器三部分。

客户端向ZooKeeper服务器注册Watcher的同时,会将Watcher对象存储在客户端的WatchManager中。

当zookeeper服务器触发watcher事件后,会向客户端发送通知, 客户端线程从 WatcherManager 中取出对应的 Watcher 对象来执行回调逻辑。

Watcher特性总结

  • 一次性:一个Watch事件是一个一次性的触发器。一次性触发,客户端只会收到一次这样的信息。
  • 异步的: Zookeeper服务器发送watcher的通知事件到客户端是异步的,不能指望可以监控到节点每次的变化,Zookeeper只能保证最终的一致性,而没法保证强一致性。
  • 轻量级:Watcher 通知很是简单,它只是通知发生了事件,而不会传递事件对象内容。
  • 客户端串行:执行客户端 Watcher 回调的过程是一个串行同步的过程。
  • 注册 watcher用getData、exists、getChildren方法
  • 触发 watcher用create、delete、setData方法

六、面试官:你对Zookeeper的数据结构都有必定了解,那讲下Zookeeper的特性吧

Zookeeper 保证了以下分布式一致性特性:

  • 顺序一致性:从同一客户端发起的事务请求,最终将会严格地按照顺序被应用到 ZooKeeper 中去。
  • 原子性:全部事务请求的处理结果在整个集群中全部机器上的应用状况是一致的,也就是说,要么整个集群中全部的机器都成功应用了某一个事务,要么都没有应用。
  • 单一视图:不管客户端连到哪个 ZooKeeper 服务器上,其看到的服务端数据模型都是一致的。
  • 可靠性:一旦服务端成功地应用了一个事务,并完成对客户端的响应,那么该事务所引发的服务端状态变动将会被一直保留下来。
  • 实时性(最终一致性): Zookeeper 仅仅能保证在必定的时间段内,客户端最终必定可以从服务端上读取到最新的数据状态。

七、面试官:你刚提到顺序一致性,那zookeeper是如何保证事务的顺序一致性的呢?

须要了解事务ID,即zxid。ZooKeeper的在选举时经过比较各结点的zxid和机器ID选出新的主结点的。zxid由Leader节点生成,有新写入事件时,Leader生成新zxid并随提案一块儿广播,每一个结点本地都保存了当前最近一次事务的zxid,zxid是递增的,因此谁的zxid越大,就表示谁的数据是最新的。

ZXID的生成规则以下:
在这里插入图片描述
ZXID有两部分组成:

  • 任期:完成本次选举后,直到下次选举前,由同一Leader负责协调写入;
  • 事务计数器:单调递增,每生效一次写入,计数器加一。

ZXID的低32位是计数器,因此同一任期内,ZXID是连续的,每一个结点又都保存着自身最新生效的ZXID,经过对比新提案的ZXID与自身最新ZXID是否相差“1”,来保证事务严格按照顺序生效的。

八、面试官:提到了Leader,你知道Zookeeper的服务器有几种角色嘛?Zookeeper下Server工做状态又有几种呢?

Zookeeper 服务器角色
Zookeeper集群中,有Leader、Follower和Observer三种角色

Leader

Leader服务器是整个ZooKeeper集群工做机制中的核心,其主要工做:

事务请求的惟一调度和处理者,保证集群事务处理的顺序性
集群内部各服务的调度者

Follower

Follower服务器是ZooKeeper集群状态的跟随者,其主要工做:

处理客户端非事务请求,转发事务请求给Leader服务器
参与事务请求Proposal的投票
参与Leader选举投票

Observer

Observer是3.3.0 版本开始引入的一个服务器角色,它充当一个观察者角色——观察ZooKeeper集群的最新状态变化并将这些状态变动同步过来。其工做:

处理客户端的非事务请求,转发事务请求给 Leader 服务器
不参与任何形式的投票

Zookeeper下Server工做状态

服务器具备四种状态,分别是 LOOKING、FOLLOWING、LEADING、OBSERVING。

1.LOOKING:寻找Leader状态。当服务器处于该状态时,它会认为当前集群中没有 Leader,所以须要进入 Leader 选举状态。

2.FOLLOWING:跟随者状态。代表当前服务器角色是Follower。

3.LEADING:领导者状态。代表当前服务器角色是Leader。

4.OBSERVING:观察者状态。代表当前服务器角色是Observer。

九、面试官:说到服务器角色是基于ZooKeeper集群的,那你画一下ZooKeeper集群部署图吧?ZooKeeper是如何保证主从节点数据一致性的呢?

ZooKeeper集群部署图
在这里插入图片描述

ZooKeeper集群是一主多从的结构:

若是是写入数据,先写入主服务器(主节点),再通知从服务器。
若是是读取数据,既读主服务器的,也能够读从服务器的。

ZooKeeper如何保证主从节点数据一致性

咱们知道集群是主从部署结构,要保证主从节点一致性问题,无非就是两个主要问题:

  • 主服务器挂了,或者重启了
  • 主从服务器之间同步数据

Zookeeper是采用ZAB协议(Zookeeper Atomic Broadcast,Zookeeper原子广播协议)来保证主从节点数据一致性的,ZAB协议支持崩溃恢复和消息广播两种模式,很好解决了这两个问题:

  • 崩溃恢复:Leader挂了,进入该模式,选一个新的leader出来
  • 消息广播: 把更新的数据,从Leader同步到全部Follower

Leader服务器挂了,全部集群中的服务器进入LOOKING状态,首先,它们会选举产生新的Leader服务器;接着,新的Leader服务器与集群中Follower服务进行数据同步,当集群中超过半数机器与该 Leader服务器完成数据同步以后,退出恢复模式进入消息广播模式。Leader 服务器开始接收客户端的事务请求生成事务Proposal进行事务请求处理。

十、面试官:Leader挂了,进入崩溃恢复,是如何选举Leader的呢?你讲一下ZooKeeper选举机制吧

服务器启动或者服务器运行期间(Leader挂了),都会进入Leader选举,咱们来看一下~假设如今ZooKeeper集群有五台服务器,它们myid分别是服务器一、二、三、四、5,如图:
在这里插入图片描述

服务器启动的Leader选举

zookeeper集群初始化阶段,服务器(myid=1-5)依次启动,开始zookeeper选举Leader~
在这里插入图片描述

- 服务器1(myid=1)启动,当前只有一台服务器,没法完成Leader选举

- 服务器2(myid=2)启动,此时两台服务器可以相互通信,开始进入Leader选举阶段

每一个服务器发出一个投票

服务器1 和 服务器2都将本身做为Leader服务器进行投票,投票的基本元素包括:服务器的myid和ZXID,咱们以(myid,ZXID)形式表示。初始阶段,服务器1和服务器2都会投给本身,即服务器1的投票为(1,0),服务器2的投票为(2,0),而后各自将这个投票发给集群中的其余全部机器。

接受来自各个服务器的投票

每一个服务器都会接受来自其余服务器的投票。同时,服务器会校验投票的有效性,是否本轮投票、是否来自LOOKING状态的服务器。

处理投票

收到其余服务器的投票,会将被人的投票跟本身的投票PK,PK规则以下:

优先检查ZXID。ZXID比较大的服务器优先做为leader。
若是ZXID相同的话,就比较myid,myid比较大的服务器做为leader。

服务器1的投票是(1,0),它收到投票是(2,0),二者zxid都是0,由于收到的myid=2,大于本身的myid=1,因此它更新本身的投票为(2,0),而后从新将投票发出去。对于服务器2呢,即再也不须要更新本身的投票,把上一次的投票信息发出便可。

统计投票

每次投票后,服务器会统计全部投票,判断是否有过半的机器接受到相同的投票信息。服务器2收到两票,少于3(n/2+1,n为总服务器),因此继续保持LOOKING状态

- 服务器3(myid=3)启动,继续进入Leader选举阶段

跟前面流程一致,服务器1和2先投本身一票,由于服务器3的myid最大,因此你们把票改投给它。此时,服务器为3票(大于等于n/2+1),因此服务器3当选为Leader。 服务器1,2更改状态为FOLLOWING,服务器3更改状态为LEADING;

- 服务器4启动,发起一次选举。

此时服务器1,2,3已经不是LOOKING状态,不会更改选票信息。选票信息结果:服务器3为4票,服务器4为1票。服务器4并更改状态为FOLLOWING;

- 服务器5启动,发起一次选举。

同理,服务器也是把票投给服务器3,服务器5并更改状态为FOLLOWING;

  • 投票结束,服务器3当选为Leader

服务器运行期间的Leader选举

zookeeper集群的五台服务器(myid=1-5)正在运行中,忽然某个瞬间,Leader服务器3挂了,这时候便开始Leader选举~
在这里插入图片描述
1.变动状态

Leader 服务器挂了以后,余下的非Observer服务器都会把本身的服务器状态更改成LOOKING,而后开始进入Leader选举流程。

2.每一个服务器发起投票

每一个服务器都把票投给本身,由于是运行期间,因此每台服务器的ZXID可能不相同。假设服务1,2,4,5的zxid分别为333,666,999,888,则分别产生投票(1,333),(2,666),(4,999)和(5,888),而后各自将这个投票发给集群中的其余全部机器。

3.接受来自各个服务器的投票

4.处理投票

投票规则是跟Zookeeper集群启动期间一致的,优先检查ZXID,大的优先做为Leader,因此显然服务器zxid=999具备优先权。

5.统计投票

6.改变服务器状态

十一、面试官: 提到在项目中使用过Zookeeper的分布式锁,讲一下zk分布式锁的实现原理吧?

Zookeeper就是使用临时顺序节点特性实现分布式锁的。

  • 获取锁过程 (建立临时节点,检查序号最小)
  • 释放锁 (删除临时节点,监听通知)

获取锁过程

  • 当第一个客户端请求过来时,Zookeeper客户端会建立一个持久节点/locks。若是它(Client1)想得到锁,须要在locks节点下建立一个顺序节点lock1.如图

在这里插入图片描述

  • 接着,客户端Client1会查找locks下面的全部临时顺序子节点,判断本身的节点lock1是否是排序最小的那一个,若是是,则成功得到锁。
    在这里插入图片描述

这时候若是又来一个客户端client2前来尝试得到锁,它会在locks下再建立一个临时节点lock2
在这里插入图片描述

  • 客户端client2同样也会查找locks下面的全部临时顺序子节点,判断本身的节点lock2是否是最小的,此时,发现lock1才是最小的,因而获取锁失败。获取锁失败,它是不会甘心的,client2向它排序靠前的节点lock1注册Watcher事件,用来监听lock1是否存在,也就是说client2抢锁失败进入等待状态。
    在这里插入图片描述
  • 此时,若是再来一个客户端Client3来尝试获取锁,它会在locks下再建立一个临时节点lock3
    在这里插入图片描述
  • 一样的,client3同样也会查找locks下面的全部临时顺序子节点,判断本身的节点lock3是否是最小的,发现本身不是最小的,就获取锁失败。它也是不会甘心的,它会向在它前面的节点lock2注册Watcher事件,以监听lock2节点是否存在。
    在这里插入图片描述

释放锁

咱们再来看看释放锁的流程,zookeeper的客户端业务完成或者故障,都会删除临时节点,释放锁。若是是任务完成,Client1会显式调用删除lock1的指令
在这里插入图片描述

若是是客户端故障了,根据临时节点得特性,lock1是会自动删除的
在这里插入图片描述

lock1节点被删除后,Client2可开心了,由于它一直监听着lock1。lock1节点删除,Client2马上收到通知,也会查找locks下面的全部临时顺序子节点,发下lock2是最小,就得到锁。
在这里插入图片描述

同理,Client2得到锁以后,Client3也对它虎视眈眈

12.面试官:好,最后一道题,你说说dubbo和Zookeeper的关系吧,为何选择Zookeeper做为注册中心?

dubbo的注册中心能够选Zookeeper,memcached,redis等。为何选择Zookeeper,由于它的功能特性

  • 命名服务,服务提供者向Zookeeper指定节点写入url,完成服务发布。
  • 负载均衡,注册中心的承载能力有限,而Zookeeper集群配合web应用很容易达到负载均衡。
  • zk支持监听事件,特别适合发布/订阅的场景,dubbo的生产者和消费者就相似这场景。
  • 数据模型简单,数据存在内存,可谓高性能
  • Zookeeper其余特色均可以讲一下

同时提供【免费】的Java架构学习资料,学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。须要的朋友能够点击连接: 点这个,点这个。 暗号:csdn。在这里插入图片描述