zookeeper面试题

zookeeper相关

介绍一下zookeeper

ZooKeeper是一个分布式应用程序协调服务

主要用于数据的发布订阅(集群的配置管理和服务发现),集群的负载均衡(负载均衡算法),提供命名服务(通过指定的名字来获取资源或者服务的地址,提供者的信息。),和分布式协调通知(监控集群的服务器状态及时做出服务调整)

zookeeper的服务器角色主要有leader,follower,observer,leader负责处理事务性请求和对集群内各个服务器的调度,follower主要处理客户端非事务请求,转发事物请求给Leader服务器,

参与事务请求提议的投票,参与Leader选举投票。observer只处理非事务请求不参与投票

zookeeper集群的机器往往是部署奇数台,因为很多的处理都是投票决定的,超过半数通过就算通过比如leader选举和事务操作,奇数台跟偶数台效果一样,所以一般就取奇数

分布式协调技术

分布式协调技术 主要是对分布式环境当中多个进程之间的同步控制,让他们有序的去访问某种临界资源,防止造成"脏数据"的后果。

 

分布式系统

分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。

分布式应用:应用程序分布在不同计算机上,通过网络来共同完成一项任务的工作方式。

 

zookeeper是如何保证事务的顺序一致性的

所有的proposal(事务请求提议)都在被提出的时候会首先会向其他的server发出事务执行请求,如果超过半数的机器都能执行并且能够成功,那么就会开始执行

 

zookeeper常用端口

1、2181:对cline端提供服务

 

2、3888:选举leader使用

 

3、2888:集群内机器通讯使用(Leader监听此端口)

都可以修改

 

zookeeper的数据模型

是一个类似unix文件系统的树形层次结构,构成一个有层次的命名空间,树上的每个节点我们称为znode,每个znode上可以保存数据,也可以拥有子节点

zonde

znode 具有原子性操作,读操作将获取与节点相关的所有数据,写操作也将替换掉节点的所有数据。

Znode 有两种,分别为临时节点和永久节点。

节点的类型在创建时即被确定,并且不能改变。

临时节点:该节点的生命周期依赖于创建它们的会话。一旦会话结束,临时节点将被自动删除,当然可以也可以手动删除。临时节点不允许拥有子节点。

永久节点:该节点的生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,他们才能被删除。

 

leader选举

机器中为什么会有master;

在分布式环境中,有些业务逻辑只需要集群中的某一台机器进行执行,其他的机器可以共享这个结果,这样可以大大减少重复计算,提高性能,于是就需要进行master选举。

 

 

(zookeeper的应用场景

数据发布订阅

即注册中心,如dubbo的注册中心。

数据发布/订阅 顾名思义就是一方把数据发布出来,另一方通过某种手段可以得到这些数据 通常数据订阅有两种方式:推模式和拉模式,推模式一般是服务器主动向客户端推送信息,拉模式是客户端主动去服务器获取数据(通常采用定时轮询的方式),ZK采用两种方式相互结合发布者将数据发布到ZK集群节点上,订阅者通过一定的方法告诉服务器,我对哪个节点感兴趣,服务器在这些节点的数据发生变化时,就通知客户端,客户端得到通知后可以去服务器获取数据信息。

主要通过对节点管理做到发布以及事件监听做到订阅。

配置管理和服务发现

发布订阅模式在分布式系统的典型应用有, 配置管理和服务发现。

配置管理:是指如果集群中机器拥有某些相同的配置,并且这些配置信息需要动态的改变,我们可以使用发布订阅模式,对配置文件做统一的管理,让这些机器各自订阅配置文件的改变,当配置文件发生改变的时候这些机器就会得到通知,把自己的配置文件更新为最新的配置

服务发现:是指对集群中的服务上下线做统一的管理,每个工作服务器都可以作为数据的发布方,向集群注册自己的基本信息,而让模型机器作为订阅方,订阅工作服务器的基本信息,当工作服务器的基本信息发生改变时如上下线,服务器的角色和服务范围变更,监控服务器就会得到通知,并响应这些变化。

 

负载均衡

如为kafka集群做负载均衡

服务器启动的时候会把DB节点挂到ZK上面。ZK分为两种节点,一种是临时节点,一种是长久节点。如果长久节点挂掉了,会和临时节点建立连接。采用随机算法,访问节点。

 

1.临时节点出现问题的时候,节点会自动的从ZK上删除,那么ZK服务器列表就是最新的可用列表。

2.客户端随机与之建立连接。

3.当客户端发现不可用的时候可再次从ZK上获取可用的DB信息,当然也可以在刚获取的哪个列表里移除掉不可用的连接后再随机选择一个DB与之连接。

 

Zookeeper类似于一棵节点树,当服务提供者启动时,将服务器的名称、地址以节点的信息添加到配置中心,而服务消费中通过服务器名称以及配置中心来获得需要调用的服务节点下的服务地址,再利用负载均衡算法选取其中的某一台服务器进行调用。

 

命名服务

顾名思义,就是提供名称的服务,例如数据库表格ID,一般用的多的用两种ID,一种是自动增长的ID,一直是UUID。两种ID各有缺陷,自动增持的ID局限在单库,单表中使用,不能再分布式环境下使用,UUID可以在分布式中使用,但是ID没有规则难以理解,而且字段较多。我们可以借用ZK来生成一个顺序增长的,可以在集群环境下使用的,命名易于理解的ID

zookeeper的节点结构天然支持命名服务,即把信息集中存储,并以树状管理,方便统一查阅。

 

分布式应用中,通常需要有一套完整的命名规则,既能够产生唯一的名称又便于人识别和记住

命名服务是指利用Zookeeper很容易创建一个全局的路径,而这个路径就可以作为一个名字,它可以指向集群中的集群,提供的服务的地址,远程对象等。简单来说使用Zookeeper做命名服务就是用路径作为名字,路径上的数据就是其名字指向的实体。

 

阿里巴巴集团开源的分布式服务框架Dubbo中使用ZooKeeper来作为其命名服务,维护全局的服务地址列表。

分布式协调通知)

心跳检测

在分布式系统中,我们常常需要知道某个机器是否可以用,传统的开发中,可以通过pin g某个主机来实现,ping得通说明对方是否可用的,相反是不可用的,ZK中我们让所有的机器都注册一个临时节点。然后看哪个机器的服务没有被挂上,就证明哪个机器有问题

 

zookeeper的特点

顺序一致性:按照客户端发送请求的顺序更新数据。

原子性:更新要么成功,要么失败,不会出现部分更新。

单一性 :无论客户端连接哪个server,都会看到同一个视图。

可靠性:一旦数据更新成功,将一直保持,直到新的更新。

及时性:客户端会在一个确定的时间内得到最新的数据

 

zookeeper的集群搭建

下载解压zookeeper的安装包,

将conf/zoo_sample.cfg拷贝一份命名为zoo.cfg,也放在conf目录下。然后按照如下值修改其中的配置:

设置心跳时间tickTime

Zookeeper 保存数据的目录dataDir

客户端连接服务端的接口clientPort,默认端口:2181

集群的ip及端口和选举leader用的端口如:

server.1=192.168.0.1:3888:4888

server.2=192.168.0.2:3888:4888

server.3=192.168.0.3:3888:4888

 

然后依次启动集群的服务器zkServer.sh start

./zkServer.sh status 查看zk服务器状态(显示是否可用是主还是从)

zookeeper为什么要奇数台

我们通常说Zookeeper安装在2N-1个节点。

集群中只要有超过过半的机器是正常工作的,那么整个集群对外就是可用的

Zookeeper的大部分操作都是通过选举产生的。比如,标记一个写是否成功是要在超过一半节点发送写请求成功时才认为有效。同样,Zookeeper选择领导者节点也是在超过一半节点同意时才有效。最后,Zookeeper是否正常是要根据是否超过一半的节点正常才算正常。这是基于CAP的一致性原理。

安装5个节点和6个节点的Zookeeper没有区别,因为失效节点的容忍度是一致性的都是2,那么这样的话,就没有必要多安装一个节点了。

对于2n和2n-1台机器的失效节点容忍度是一样的,都是n-1,所以为了更加高效,没有必要增加一个不必要的节点。

zookeeper 服务器的角色

 

Leader,Follower,Observer

Leader

 Leader服务器是整个zookeeper集群工作机制中的核心,其主要工作有以下两个。

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

事务请求:

改变服务器状态的请求称为事务请求(创建节点、更新数据、删除节点、创建会话等)

Follower

Follower服务器是zookeeper集群状态的跟随者,其主要工作有以下三个。

 

处理客户端非事务请求,转发事物请求给Leader服务器。

参与事务请求Proposal的投票。

参与Leader选举投票。

 

Proposal:

提议,每个事务请求都需要集群中过半机器投票认可才能被真正应用到内存数据库中,

Observer

和Follower唯一的区别在于,Observer不参与任何形式的投票,包括事物请求Proposal的投票和Leader选举投票。简单地讲,Observer服务器只提供非事物服务,通常用于在不影响集群事务处理能力的前提下提升集群的非事务处理能力,提高读取速度。。

分布式锁

概念:

在分布式的环境下保证线程安全的一种机制

为什么会出现分布式锁:

有的时候,我们需要保证一个方法在同一时间内只能被同一个线程执行。在单机环境中,Java中其实提供了很多并发处理相关的API,但是这些API在分布式场景中就无能为力了。也就是说单纯的Java Api并不能提供分布式锁的能力。

分布式锁的实现方式

一、数据库锁

  1. 基于MySQL锁表

该实现方式完全依靠数据库唯一索引来实现,当想要获得锁时,即向数据库中插入一条记录,释放锁时就删除这条记录。

  1. 采用乐观锁增加版本号

 

  根据版本号来判断更新之前有没有其他线程更新过,如果被更新过,则获取锁失败。

二、缓存锁

  1. 基于setnx、expire两个命令来实现

基于setnx(set if not exist)的特点,当缓存里key不存在时,才会去set,否则直接返回false。如果返回true则获取到锁,否则获取锁失败,为了防止死锁,我们再用expire命令对这个key设置一个超时时间来避免。但是这里看似完美,实则有缺陷,当我们setnx成功后,线程发生异常中断,expire还没来的及设置,那么就会产生死锁。

  1. RedLock算法

redlock算法是redis作者推荐的一种分布式锁实现方式

三、zookeeper分布式锁

首先我们来了解一下zookeeper的特性,看看它为什么适合做分布式锁,

  zookeeper是一个为分布式应用提供一致性服务的软件,它内部是一个分层的文件系统目录树结构,规定统一个目录下只能有一个唯一文件名。

 

  数据模型:

永久节点:节点创建后,不会因为会话失效而消失

临时节点:与永久节点相反,如果客户端连接失效,则立即删除节点

顺序节点:与上述两个节点特性类似,如果指定创建这类节点时,zk会自动在节点名后加一个数字后缀,并且是有序的。

 

  监视器(watcher):

 

当创建一个节点时,可以注册一个该节点的监视器,当节点状态发生改变时,watch被触发时,ZooKeeper将会向客户端发送且仅发送一条通知,因为watch只能被触发一次。

 

  根据zookeeper的这些特性,我们来看看如何利用这些特性来实现分布式锁:

 

  1. 创建一个锁目录lock

 

  2. 希望获得锁的线程A就在lock目录下,创建临时顺序节点

 

  3. 获取锁目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁

 

  4. 线程B获取所有节点,判断自己不是最小节点,设置监听(watcher)比自己次小的节点(只关注比自己次小的节点是为了防止发生“羊群效应”)

 

  1. 线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是最小的节点,获得锁。

 

三种分布式锁的比较

数据库锁:

 

优点:直接使用数据库,使用简单。

 

缺点:分布式系统大多数瓶颈都在数据库,使用数据库锁会增加数据库负担。

 

缓存锁:

 

优点:性能高,实现起来较为方便,在允许偶发的锁失效情况,不影响系统正常使用,建议采用缓存锁。

 

缺点:通过锁超时机制不是十分可靠,当线程获得锁后,处理时间过长导致锁超时,就失效了锁的作用。

 

zookeeper锁:

 

优点:不依靠超时时间释放锁;可靠性高;系统要求高可靠性时,建议采用zookeeper锁。

 

缺点:性能比不上缓存锁,因为要频繁的创建节点删除节点。

 

从理解的难易程度角度(从低到高)

数据库 > 缓存 > Zookeeper

 

从实现的复杂性角度(从低到高)

Zookeeper >= 缓存 > 数据库

 

从性能角度(从高到低)

缓存 > Zookeeper >= 数据库

 

从可靠性角度(从高到低)

Zookeeper > 缓存 > 数据库

 

 

ZK选举过程

当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的Server都恢复到一个正确的状态。Zk的选举算法使用ZAB协议:

 

选举线程由当前Server发起选举的线程担任,其主要功能是对投票结果进行统计,并选出推荐的Server;

选举线程首先向所有Server发起一次询问(包括自己);

选举线程收到回复后,验证是否是自己发起的询问(验证zxid是否一致),然后获取对方的id(myid),并存储到当前询问对象列表中,最后获取对方提议的leader相关信息(id,zxid),并将这些信息存储到当次选举的投票记录表中;

收到所有Server回复以后,就计算出zxid最大的那个Server,并将这个Server相关信息设置成下一次要投票的Server;

线程将当前zxid最大的Server设置为当前Server要推荐的Leader,如果此时获胜的Server获得n/2 + 1的Server票数, 设置当前推荐的leader为获胜的Server,将根据获胜的Server相关信息设置自己的状态,否则,继续这个过程,直到leader被选举出来。

通过流程分析我们可以得出:要使Leader获得多数Server的支持,则Server总数最好是奇数2n+1,且存活的Server的数目不得少于n+1

 

master/slave之间通信

Storm:定期扫描

PtBalancer:节点监听

客户端对ServerList的轮询机制是什么

随机,客户端在初始化( new ZooKeeper(String connectString, int sessionTimeout, Watcher watcher) )的过程中,将所有Server保存在一个List中,然后随机打散,形成一个环。之后从0号位开始一个一个使用。

 

ZooKeeper集群中服务器之间是怎样通信的?

Leader服务器会和每一个Follower/Observer服务器都建立TCP连接,同时为每个F/O都创建一个叫做LearnerHandler的实体。LearnerHandler主要负责Leader和F/O之间的网络通讯,包括数据同步,请求转发和Proposal提议的投票等。Leader服务器保存了所有F/O的LearnerHandler。

 

zookeeper是否会自动进行日志清理?如何进行日志清理?

zk自己不会进行日志清理,需要运维人员进行日志清理

 

zookeeper的基本数据模型

类似Linux文件系统的节点模型

其节点有如下有趣而又重要的特性:

1、同一时刻多台机器创建同一个节点,只有一个会争抢成功。利用这个特性可以做分布式锁。

2、临时节点的生命周期与会话一致,会话关闭则临时节点删除。这个特性经常用来做心跳,动态监控,负载等动作。

3、顺序节点保证节点名全局唯一。这个特性可以用来生成分布式环境下的全局自增长id。

zookeeper提供的原语服务

创建节点

删除节点

更新节点

获取节点信息

权限控制

事件监听

 

一致性协议

什么是Zab协议?

Zab协议 的全称是 Zookeeper Atomic Broadcast (Zookeeper原子广播)。

Zookeeper 是通过 Zab 协议来保证分布式事务的最终一致性。依赖Zab协议来实现数据一致性

Zab协议是为分布式协调服务Zookeeper专门设计的一种 支持崩溃恢复的原子广播协议

 

 

该协议的功能:

(1)集群在半数以下节点宕机的情况下,能正常对外提供服务;

(2)客户端的写请求全部转交给leader来处理,leader需确保写变更能实时同步给所有follower及observer;

(3)leader宕机或整个集群重启时,需要确保那些已经在leader服务器上提交的事务最终被所有服务器都提交,确保丢弃那些只在leader服务器上被提出的事务,并保证集群能快速恢复到故障前的状态。

 

posted @ 2023-02-02 09:53  星光闪闪  阅读(131)  评论(0)    收藏  举报