zookeeper面试整理
Posted 潜行前行
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了zookeeper面试整理相关的知识,希望对你有一定的参考价值。
zookeeper
1 数据结构和四种节点
- Zookeeper 为了保证高吞吐和低延迟,在内存中维护了这个树状的目录结构,这种特性使得Zookeeper 不能用于存放大量的数据,每个节点的存放数据上限为 1M
- 四种节点
- 永久节点:除非手动删除,否则节点一直存在于Zookeeper上
- 临时节点:临时节点的生命周期与客户端会话绑定,一旦客户端会话失效(客户端与zookeeper连接断开不一定会话失效),那么这个客户端创建的所有临时节点都会被移除
- 永久顺序节点:基本特性同永久节点,只是增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字
- 临时顺序节点:基本特性同临时节点,增加了顺序属性,节点名后边会追加一个由父节点维护的自增整型数字
2 zab协议
- ZAB协议包括两种基本的模式:崩溃恢复和消息广播
- 当整个zookeeper集群刚刚启动或者Leader服务器宕机、重启或者网络故障导致不存在过半的服务器与Leader服务器保持正常通信时,所有进程(服务器)进入崩溃恢复模式,首先选举产生新的Leader服务器,然后集群中Follower服务器开始与新的Leader服务器进行数据同步
- 当集群中超过半数机器与该Leader服务器完成数据同步之后,退出恢复模式进入消息广播模式,Leader服务器开始接收客户端的事务请求生成事物提案来进行事务请求处理
- 服务器三种角色
- Leader:事务请求的唯一调度和处理者,保证集群事务处理的顺序性
- Follower:处理客户端的非事务请求,转发事务请求给Leader服务
器;参与事务请求Proposal的投票;参与Leader选举投票 - Observer:3.3.0版本以后引入的一个服务器角色,在不影响集群事务处理能力的基础上提升集群的非事务处理能力;处理客户端的非事务请求,转发事务请求给Leader服务器;不参与任何形式的投票
- 服务器四种状态
- LOOKING:寻找Leader状态。当服务器处于该状态时,它会认为当前集群中没有Leader,因此需要进入Leader选举状态
- FOLLOWING:跟随者状态。表明当前服务器角色是Follower
- LEADING:领导者状态。表明当前服务器角色是Leader
- OBSERVING:观察者状态。表明当前服务器角色是Observer
3 Leader 选举
- 每一个节点都会维护三个最重要的信息:epoch、zxid、myid。epoch 代表选举的轮次,优先比较,如果相同则继续比较下一级。zxid 代表本节点处理过的最大事务ID,越大代表当前节点经手的写请求越多,知道的也就越多,第二优先级比较,如果还相同则比较 myid,myid 整个集群中不能重复,所以最终一定能分出胜负。胜利的节点当选 Leader
- Leader选举是保证分布式数据一致性的关键所在。当Zookeeper集群中的一台服务器出现以下两种情况之一时,需要进入Leader选举。
- (1) 服务器初始化启动。
- (2) 服务器运行期间无法和Leader保持连接
- 1. 服务器启动时期的Leader选举
- (1) 每个Server发出一个投票。由于是初始情况,Server1和Server2都会将自己作为Leader服务器来进行投票,每次投票会包含所推举的服务器的myid和 zxid,使用(myid, zxid)来表示,此时Server1的投票为(1, 0),Server2的投票为(2, 0),然后各自将这个投票发给集群中其他机器。其中 zxid 高32位是 epoch 信息
- (2) 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器。
- (3) 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK,PK规则如下
- 优先检查 zxid。zxid 比较大的服务器优先作为Leader。
- 如果 zxid 相同,那么就比较 myid。myid 较大的服务器作为Leader服务器。
- 对于Server1而言,它的投票是(1, 0),接收Server2的投票为(2, 0),首先会比较两者的ZXID,均为0,再比较myid,此时Server2的 myid 最大,于是更新自己的投票为(2, 0),然后重新投票,对于Server2而言,其无须更新自己的投票,只是再次向集群中所有机器发出上一次投票信息即可。
- (4) 统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于Server1、Server2而言,都统计出集群中已经有两台机器接受了(2, 0)的投票信息,此时便认为已经选出了Leader。
- (5) 改变服务器状态。一旦确定了Leader,每个服务器就会更新自己的状态,如果是 follower,那么就变更为FOLLOWING,如果是 Leader,就变更为 LEADING。
- 2. 服务器运行时期的Leader选举
- (1) 变更状态:Leader挂后,余下的非Observer服务器都会讲自己的服务器状态变更为LOOKING,然后开始进入Leader选举过程。
- (2) 每个Server会发出一个投票。在运行期间,每个服务器上的ZXID可能不同,此时假定Server1的 zxid 为123,Server2 的 zxid 为122;在第一轮投票中,Server1和Server2 都会投自己,产生投票(1, 123),(2, 122),然后各自将投票发送给集群中所有机器。
- (3) 接收来自各个服务器的投票。与启动时过程相同。
- (4) 处理投票。与启动时过程相同,此时,Server1 将会成为Leader。
- (5) 统计投票。与启动时过程相同。
- (6) 改变服务器的状态。与启动时过程相同
4 zookeeper 是强一致性吗
- 不是强一致性,但是保证最终一致性
5 zookeeper 原子性是怎样实现的
- 原子性:所有事务请求的处理结果在整个集群中所有机器的应用情况是一致的,也就是说,要么整个集群中所有的机器都成功应用了某个事务,要么都没有应用
- zk 的事务操作都在 leader 操作查成功,再由 follower ack 同步,也就是说如果 leader 返回的结果不存在执行到一半的事务操作
6 zookeeper 的 watch 机制
- Zookeeper允许客户端向服务端的某个Znode注册一个Watcher监听,当服务端的一些指定事件触发了这个Watcher,服务端会向指定客户端发送一个事件通知来实现分布式的通知功能,然后客户端根据Watcher通知状态和事件类型做出业务上的改变
- 其实就是回调通知,开发者声明一个 callback 的对象,在 Java 的客户端中这个接口是 Watcher,ZK 服务端提供了一些方法,比如getData、exists 或者最新版本中的 addWatch 都可以用来向 ZK 注册回调通知,而向服务端发送的回调通知,只会告诉服务端我当前的这个路径需要被通知,服务端得知后,会在内存中记录下来,路径和客户端之间的关系,客户端自己也需要记录下来,路径和具体回调的关系
- 当被订阅的路径发生事件的时候,服务端就会从内存中的记录去查看有没有需要通知的客户端,有的话会发送一个通知的请求给客户端,客户端收到通知后,就会从本地的记录中取出对应的回调对象去执行 callback 方法
7 watch监听是永久的吗,有几种触发 API
- 上面提到的 getData、exists 以及 getChildren 注册的通知都是一次性的,当服务端通知过一次后,就会删除内存中的记录,之后如果仍然需要通知的话,客户端就要去继续注册
- 而触发 API 则有 create、delete、setData
8 顺序一致性
- zookeeper 采用了全局递增的事务 Id 来标识,所有的 proposal(提议)都在被提出的时候加上了zxid,zxid 实际上是一个 64 位的数字,高 32 位是 epoch( 时期; 纪元; 世; 新时代)用来标识leader 周期,如果有新的 leader 产生出来,epoch会自增,低 32 位用来递增计数
- 当新产生 proposal 的时候,会依据数据库的两阶段过程,首先会向其他的 server 发出事务执行请求,如果超过半数的机器都能执行并且能够成功,那么就会认为执行成功
9 zk的应用场景
- 配置维护:
- 若集群中服务器的配置文件需要进行修改,那么我们就需要逐台修改这些服务器中的配置文件。如果我们集群服务器比较少,那么这些修改还不是太麻烦,但如果集群服务器特别多,就很麻烦
- zk 可以通过“发布/订阅模型”实现对集群配置文件的管理与维护
- 命名服务
- 分布式协调/通知
- Master选举
- 分布式锁
10 为什么RocketMQ不使⽤Zookeeper作为注册中呢?
- 根据CAP理论,同时最多只能满两个点,zookeeper满足的是CP,也就是说zookeeper并不能保证 服务的可用性,zookeeper在进举选举的时候,整个选举的时间太长,期间整个集群都处于不可用的状 态,对于注册中心来说肯定是不能接受的,作为服务发现来说就应该是为可用性来设计
11 ZK 是怎么保存和整理数据的吗
- 内存中和磁盘上
- 内存中的数据其实是一个树形结构,从/ 根节点开始,逐级向下用/ 分割,每一个节点下面还可以有多个子节点,就类似于 Unix 中的目录结构,但在实际中,ZK 是使用一个 HashMap 去存储整个树形结构的数据的,key 是对应的全路径字符串,value 则是一个节点对象,包含了节点的各种信息
- 在磁盘上规定了两种文件类型,一种是 log 文件,一种是 snapshot。log 文件是增量记录,负责对每一个写请求进行保存,snapshot 文件是全量记录,是对内存的快照
12 zk怎么保证 内存中的数据和磁盘中的数据的一致性
- 真正的强一致性,ZK 无法保证。对于每一次的写请求,ZK 是采取先记录磁盘再修改内存的,所以保证了如果出现意外的话,优先记录磁盘可以尽可能的保证数据的完整。如果 ZK 是正常退出的话,也会强制刷磁盘文件和生成 snapshot,保证了一致性,但如果是非正常退出的话,极端情况下的一部分数据是会丢失的
13 ZooKeeper 怎么保证主从节点的状态同步?
- Leader 在接受到写请求后,会发起提案,然后等待其他节点的 ACK,这个 ACK 是要求半数以上通过才能继续下去的,所以能收到半数以上的 ACK 说明集群中的一半以上都已经完成了本地磁盘的归档,自然是保证了主从之间的数据同步
- 数据同步的四种策略
- 直接差异化同步(DIFF同步)
- 先回滚再差异化同步(TRUNC+DIFF同步)
- 仅回滚同步(TRUNC同步)
- 全量同步(SNAP同步)
以上是关于zookeeper面试整理的主要内容,如果未能解决你的问题,请参考以下文章