面试时,只要面试官看到你的简历上写着Zookeeper(熟悉,掌握),那么你至少要准备接下来的11个连续问题。NO1:什么是zookeeper?ZooKeeper是一种分布式、开源的分布式应用协调服务。它是Google的Chubby的开源实现(Chubby不是开源的)。它是集群的管理者,监控着集群中各个节点的状态,并根据节点提交的反馈进行下一步的合理操作。最终,将提供给用户一个易于使用的界面和一个高性能、稳定的系统。Zookeeper最常见的使用场景之一就是充当服务生产者和服务消费者的注册中心。服务生产者将自己的服务注册到Zookeeper中心,服务消费者调用服务时首先在Zookeeper中进行搜索。服务,获取服务生产者的详细信息后,再调用服务生产者的内容和数据。一个简单的示例图如下:NO2:你知道Zookeeper的系统架构吗?ZooKeeper的架构图中我们需要了解和掌握的主要有:(1)ZooKeeper分为服务端(Server)和客户端(Client),客户端可以连接到整个ZooKeeper服务的任意一个服务端(除非leaderServes参数被显式设置,领导者不允许接受客户端连接)。(2)客户端使用并维护一个TCP连接,通过它发送请求、接收响应、获取观察到的事件和发送信息。如果此TCP连接中断,客户端将自动尝试连接到另一个ZooKeeper服务器。当客户端第一次连接到ZooKeeper服务时,一个可以接受连接的ZooKeeper服务器会为客户端建立一个会话。当客户端连接到另一台服务器时,会话将由新服务器重新建立。(3)上图中的每个Server代表一台安装了Zookeeper服务的机器,即提供Zookeeper服务的整个集群(或伪集群);(4)组成ZooKeeper服务的服务器之间必须相互理解。它们在内存中维护状态图像,以及持久存储中的事务日志和快照。只要大部分服务器可用,ZooKeeper服务就可用;(5)ZooKeeper启动时,会从实例中选出一个leader,leader负责处理数据的更新等操作,更新操作成功的标志是当且仅当大多数服务器都成功修改了其中的数据记忆。每个服务器在内存中存储一??份数据副本。(6)Zookeeper可以集群复制,集群之间通过Zab协议(ZookeeperAtomicBroadcast)保持数据一致性;(7)Zab协议由两个阶段组成:leader选举阶段和AtomicBrodcast阶段。a)集群中会选举出一个leader,其他机器称为follower。所有写操作都发送给领导者,所有更新都通过广播告诉跟随者。b)当leader崩溃或者leader失去大部分follower时,需要重新选举一个新的leader来恢复所有服务器到正确的状态。c)当leader选举出来,大部分server都完成了与leader的状态同步,leader选举过程结束,进入Atomicbrodcast过程。d)AtomicBrodcast同步leader和follower之间的信息,保证leader和follower的系统状态相同。NO3:能谈谈Zookeeper的工作原理吗?Zookeeper的核心是原子广播。这种机制保证了服务器之间的同步。实现这种机制的协议称为Zab协议。Zab协议有两种模式,分别是恢复模式(主选举)和广播模式(同步)。Zab协议的全称是ZookeeperAtomicBroadcast**(ZookeeperAtomicBroadcast)。Zookeeper使用Zab协议来保证分布式事务的最终一致性。Zab协议要求每个Leader都经过三个阶段:发现、同步和广播。当服务启动或领导者崩溃后,Zab进入恢复模式。当领导者被选举出来,并且大部分服务器完成与领导者的状态同步时,恢复模式结束。状态同步确保领导者和服务器具有相同的系统状态。为了保证事务的顺序一致性,zookeeper使用一个递增的事务id号(zxid)来标识事务。所有提案在提出时都会加上zxid。在实现中,zxid是一个64位的数字,它的高32位被epoch用来标识leader关系是否发生了变化。每选出一个leader,都会有一个新的epoch,用来标识该leader当前的执政时期。第32位用于向上计数。纪元:可以理解为皇帝的年号。当新的帝王产生时,就会有新的纪元年号。每个Server在工作过程中有三种状态:LOOKING:当前Server不知道leader是谁,正在寻找。LEADING:ThecurrentServeristheelectedleader.FOLLOWING:leader已经选出,当前Server与其同步。NO4:Zookeeper为什么要这样设计?ZooKeeper的设计目的是提供高性能、高可用、顺序一致的分布式协调服务,并保证数据的最终一致性。高性能(简单数据模型)数据节点以树状结构组织;所有数据节点都存储在内存中;Follower和Observer直接处理非事务性请求;高可用(搭建集群)一半以上的机器存活,服务可以正常运行自动Leader选举顺序一致性(事务操作的顺序)每个事务请求都会转发给Leader去处理每个事务,并且一个全局唯一的增量id(zxid,64位:epoch+auto-incrementid)将分配给最终一致性通过提议的投票方式,保证交易提交的可靠性。提议的投票方式只能保证Client收到交易提交成功后,一半以上的节点可以看到最新的数据NO5:你知道Zookeeper中有哪些角色吗?系统模型:领导者(leader)Leader服务器为客户端提供读写服务。负责投票的发起和决议,更新系统状态。Learner(学习者)Follower(追随者)Follower服务器为客户端提供读服务,参与Leader选举过程,参与写操作“一半以上写成功”策略。Observer(观察者)Observer服务器为客户端提供读服务,不参与Leader选举过程,不参与写操作“超过半数写成功”策略。它用于在不影响写入性能的情况下提高集群的读取性能。客户(client):服务请求发起者。NO6:你熟悉Zookeeper节点ZNode和相关属性吗?节点有哪些类型?Znodes有两种类型:Persistent(持久):客户端和服务器断开连接后,创建的节点不会被删除(默认)。Ephemeral:客户端和服务器断开连接后,创建的节点自行删除。Znode有四种形式:持久目录节点(PERSISTENT):客户端与Zookeeper断开连接后,该节点仍然存在持久序号目录节点(PERSISTENT_SEQUENTIAL)客户端与Zookeeper断开连接后,该节点仍然存在。只是Zookeeper按顺序编号节点名:临时目录节点(EPHEMERAL)客户端与Zookeeper断开连接后,节点被删除:临时序号目录节点(EPHEMERAL_SEQUENTIAL)客户端与Zookeeper断开连接后,节点被删除Delete,但是Zookeeper会对节点名称进行序列编号“注意”:创建ZNode时,设置序列ID,ZNode名称后会附加一个值。序列号是父节点维护的一个单调递增的计数器。节点属性是什么?一个znode节点不仅可以存储数据,还具有其他一些特殊的属性。接下来我们创建一个/test节点来分析其各个属性的含义。[zk:localhost:2181(CONNECTED)6]get/test456cZxid=0x59ac//ctime=MonMar3015:20:08CST2020mZxid=0x59admtime=MonMar3015:22:25CST2020pZxid=0x59accversion=0dataVersion=2aclVersion=NO0ephemery=L03numx属性选择请简要描述过程。Zookeeper的核心是原子广播。这种机制保证了服务器之间的同步。实现这种机制的协议称为Zab协议。Zab协议有两种模式,分别是恢复模式(主选举)和广播模式(同步)。当服务启动或领导者崩溃后,Zab进入恢复模式。当领导者被选举出来,并且大部分服务器完成与领导者的状态同步时,恢复模式结束。状态同步确保领导者和服务器具有相同的系统状态。Leader选举是保证分布式数据一致性的关键。选举主要有两种场景:初始化和不可用的领导者。当zk集群中的某台服务器出现以下两种情况之一时,就会开始leader选举。服务器初始化并启动。服务器在运行时无法保持与领导者的连接。当一台机器进入leader选举过程时,当前集群还可能处于以下两种状态。集群中已经有一个领导者。集群中确实没有领导者。首先,在第一种情况下,通常集群中的某台机器启动的比较晚,而在它启动之前,集群已经在正常工作,也就是已经有了leaderserver。当机器尝试选举领导者时,它会被告知当前服务器的领导者信息。只需要和leader机器建立连接,进行状态同步即可。关键是leader不可用,此时的leader选择系统。投票信息包含两个基本信息。sid:serverid,用于标识本机在集群中的序号。zxid:zookeeper事务id号。ZooKeeper状态的每一次变化都对应一个递增的Transactionid,称为zxid。由于zxid的增量特性,如果zxid1小于zxid2,则zxid1必须出现在zxid2之前。创建任意一个节点,或者更新任意一个节点的数据,或者删除任意一个节点,都会导致Zookeeper的状态发生变化,导致zxid的值增加。投票信息以(sid,zxid)的形式标识。例如:如果当前服务器要推荐一个sid为1,zxid为8的服务器作为leader,那么投票信息可以表示为(1,8)。集群中的每台机器在发送自己的选票后,也会接受集群中其他机器的选票。机器投票。每台机器都会按照一定的规则处理从其他机器收到的选票,从而决定是否改变自己的选票。规则如下:在初始阶段,每个人都会为自己投票。当收到其他服务器的投票时,需要用自己的投票来pk别人的投票。规则如下:先检查zxid。具有较大zxid的服务器优先作为领导者。如果zxid相同则比较sid,sid大的server为leader。NO8:你了解过手表机制吗?简单的说:客户端会为某个znode注册一个watcher事件。当znode发生变化时,这些客户端会收到来自ZooKeeper的通知,然后客户端就可以根据znode进行更改。业务变更等经典使用场景:zookeeper为dubbo提供服务注册和发现,作为一个注册中心,但是大家有没有想过为什么zookeeper可以实现服务注册和发现?这就不得不说到watcher(监视器)了,zookeeper的灵魂。什么是观察者?Watcher是zooKeeper中一个非常核心的功能。clientwatcher可以监控节点及其子节点的数据变化。一旦这些状态发生变化,zooKeeper服务器就会通知所有已经设置在这个节点上的观察者。客户端,所以每个客户端都快速感知到自己监控的节点状态发生变化,并做出相应的逻辑处理。简单介绍了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给所有的consumer用户,设置watch监听的服务consumer会发送节点被删除的通知,并且consumer会根据收到的通知拉取最新的服务列表,更新本地缓存的服务列表。以上过程就是zookeeper可以实现服务注册和发现的一般原理。观察者有哪些类型?Znode节点可以设置两种watch。一种是DataWatches,它根据znode节点的数据变化触发watch事件。触发条件是getData()、exists()、setData()和create()。另一种是ChildWatches,基于znode子节点变化触发的watch事件,触发条件getChildren()、create()。当调用delete()方法删除一个znode时,DataWatches和ChildWatches会同时被触发。如果被删除的节点有父节点,父节点会触发一个ChildWatches。守望者有什么特点?节点上watch的监控事件是一次性的!客户端在指定节点上设置监控watch。一旦节点数据发生变化,通知客户端一次,客户端对该节点的监听事件将失效。.如果我们想继续监控这个节点,需要在客户端的监控回调中再次将节点的监控watch事件设置为True。否则,客户端只能收到一次节点的变化通知。NO9:那说说Zookeeper的应用场景有哪些?数据发布订阅发布订阅就是所谓的配置管理。动态更新。比如全局的配置信息,地址列表等都非常适合使用。数据发布/订阅的一个常见场景是配置中心,发布者将数据发布到ZooKeeper的一个或一系列节点,供订阅者订阅,达到动态获取数据的目的。配置信息一般有几个特点:数据量小的KV数据内容会在运行过程中动态变化。集群机器被共享和配置一致。ZooKeeper采用推拉组合的方式。推送:服务端将Wathcer事件通知推送给注册到监控节点的客户端。答:客户端收到通知后,会主动从服务端拉取最新的数据。命名服务用作分布式命名服务。要获取资源或服务的地址,请使用ZooKeeper创建全局路径。这个路径可以作为名字指向集群中的集群,提供服务的地址,或者远程对象等。统一命名服务的命名结构图如下:1.在分布式环境中,往往需要对应用/服务进行统一命名,以方便识别不同的服务。类似于域名和IP的对应关系,IP不好记,而域名好记。通过名称获取资源或服务的地址、提供者等信息。2.以层次结构组织服务/应用名称。可以将服务名称和地址信息写入ZooKeeper,客户端可以通过ZooKeeper获取可用服务列表。配置管理程序分布部署在不同的机器上,程序的配置信息放在ZooKeeper的znode下。当配置发生变化时,即znode发生变化时,可以改变zk中某个目录节点的内容,使用watch通知各个客户端改变配置。ZooKeeper配置管理结构图如下:1.在分布式环境中,配置文件管理和同步是一个普遍的问题。在集群中,所有节点的配置信息都是一致的,比如Hadoop集群。配置文件修改后,希望能快速同步到各个节点。2.配置管理可以通过ZooKeeper来实现。配置信息可以写入ZooKeeper上的Znode。每个节点都监听这个Znode。一旦Znode中的数据被修改,ZooKeeper会通知每个节点。集群管理所谓集群管理就是:是否有机器退出和加入,选举master。集群管理主要指集群监控和集群控制。前者侧重于集群运行状态的收集,后者侧重于集群的运行和控制。在开发和运维中,面对集群,往往有如下需求:想知道集群中有多少台机器在工作收集集群中每台机器的运行状态数据对机器进行在线和离线操作集群中的集群管理结构图如下:在分布式环境中,需要实时了解各个节点的状态,可以根据节点的实时状态进行一些调整。它可以通过ZooKeeper来实现。节点信息可以写入ZooKeeper上的Znode。收听此Znode以获取其实时状态更改。3、典型的应用是Hbase中的Master状态监控和选举。利用ZooKeeper的强一致性可以保证分布式高并发情况下创建节点的全局唯一性,即如果多个客户端同时请求创建/currentMaster节点,只有一个客户端请求可以在分布式通知中创建成功结束。协调与协调1、在分布式环境中,往往有一个服务需要知道它所管理的子服务的状态。a)NameNode需要知道每个Datanode的状态。b)JobTracker需要知道每个TaskTracker的状态。2、心跳检测机制可以通过ZooKeeper实现。3、信息推送可以通过ZooKeeper实现,相当于一个发布/订阅系统。分布式锁在不同节点的不同服务中。他们可能需要顺序访问一些资源。这里需要分布式锁。分布式锁有以下特点:写锁、读锁、定时锁。写锁:在zk上创建的临时无编号节点。因为是无序数,创建的时候不会自动编号,所以只有一个client拿到锁然后写。读锁:在zk上创建一个临时编号的节点,这样即使下次有客户端加入时同时创建了同一个节点,也会自动编号,获取到锁对象再进行读取。定时锁:在zk上创建一个临时编号的节点,根据编号的大小来控制锁定。分布式队列分布式队列有两种:1.当一个队列的所有成员都聚集到一起时,该队列可用,否则一直等待所有成员到达。这是一个同步队列。a)一个作业由多个任务组成,只有所有任务都完成后,作业才会运行完成。b)可以为job创建一个/job目录,然后在这个目录下为每个完成的任务创建一个临时的Znode。一旦临时节点数达到任务总数,则表明作业完成。2、队列按照FIFO的方式进行入队和出队操作,比如实现生产者和消费者模型。NO10:你知道听者的原则吗?创建一个Main()线程。在Main()线程中创建两个线程,一个负责网络连接通信(connect),一个负责监听(listener)。通过连接线程向Zookeeper发送注册的监听事件。将注册的侦听器事件添加到Zookeeper的注册侦听器列表中。当Zookeeper检测到有数据或路径发生变化时,它会将此消息发送给Listener线程。Listener线程在内部调用process()方法。NO11:为什么Zookeeper集群的数量一般都是奇数?首先需要明确zookeeper选举规则:leader选举要求可用节点数>节点总数/2。例如:标记一次写是否成功,只有超过半数的节点发送写请求成功才算有效。同样,Zookeeper对领导节点的选择只有在超过一半的节点同意时才有效。最后,Zookeeper是否正常取决于是否超过半数节点正常。这是基于CAP的一致性原则。Zookeeper有这样一个特点:只要集群中一半以上的机器正常工作,整个集群对外都是可用的。也就是说,如果有2个zookeeper,只要1个zookeeper死了,zookeeper就不能用了,因为1不超过一半,所以2个zookeeper的死亡容忍度为0;同理,如果有3个zookeeper,1个死了,还剩下2个正常的,超过一半,所以3个zookeeper的容忍度为1;类似地:2->0;两个动物园管理员,最多0个动物园管理员不可用。3->1;三个zookeeper,最多1个zookeeper不可用。4->1;四名动物园管理员,最多一名动物园管理员不可用。5->2;五名动物园管理员,最多2名动物园管理员不可用。6->2;两个zookeeper,最多0个zookeeper不可用。....你会发现一个规律,2n和2n-1的容忍度是一样的,都是n-1,所以为了更高效,何必加那个没必要的zookeeper。Zookeeper的选举策略也是需要半数以上的节点同意成为leader。如果有偶数个节点,则可能导致相同数量的选票。总结很多面试官,面试套路基本就是这样,从背景到原理,到架构体系,再到Zookeeper的内在特性,最后要求面试官说出Zookeeper的实际应用场景。
