Java面试题(8)Zookeeper

一、简述ZAB协议【zookeeper---CP】

二、Zookeeper的数据模型和节点类型 【树结构/文件目录】

三、简述ZK的命名服务、配置管理、集群管理

四、Zookeeper watch机制的原理与实现

五、ZK与Eureka的区别

 

一、简述ZAB协议【zookeeper---CP】

ZAB协议是分布式协调服务Zookeeper专门设计的一种支持崩溃恢复的原子广播协议,实现分布式数据一致性,所有客户端的请求都是写入到Leader进程中,然后,由Leader同步到其他节点,称为 Follwer。在集群数据同步的过程中,如果出现Follower节点崩溃或者Leader进程崩溃时,都会通过Zab协议来保证数据一致性

ZAB协议包括两种基本的模式:崩溃恢复消息广播

消息广播:

集群中所有的事务请求都由Leader节点来处理,其他服务器为Follower,Leader将客户端的事务请求转换为事务Proposal,并且将Proposal分发给集群中其他所有的Follower。

完成广播之后,Leader等待Follwer反馈,当有过半数的Follower反馈信息后,Leader将再次向集群内Follower广播Commit信息,Commit信息就是确认将之前的Proposal提交。

Leader节点的写入是一个两步操作,第一步是广播事务操作,第二步是广播提交操作,其中过半数指的是反馈的节点数>=N/2+1,N是全部的Follower节点数量。

崩溃恢复:

初始化集群,刚刚启动的时候

Leader崩溃,因为故障宕机

Leader失去了半数的机器支持,与集群中超过一半的节点断连

此时开启新一轮Leader选举,选举产生的Leader会与过半的Follower进行同步,使数据一致,当与过半的机器同步完成后,就推出恢复模式,然后进入消息广播模式。

整个Zookeeper集群的一致性保证就是在上面两个状态之前的切换,当Leader服务正常时,就是正常的消息广播模式;当Leader不可用时,则进入崩溃恢复模式,崩溃恢复阶段会进行数据同步,完成以后,重新进入消息广播阶段。

Zxid 是Zab协议的一个事务编号,Zxid是一个64位的数字,其中低32位是一个简单的单调递增计数器,针对客户端每一个事务请求,计数器加1;而高32位则代表Leader周期 年代的编号。

Leader周期可以理解为当集群所处的年代或周期,每当有一个新的Leader选举出现时,就会以这个Leader服务器上取出其本地日志中最大事务的Zxid,并从中读取epoch值,然后加1,以此作为新的周期id,高32位代表了每代Leader的唯一性,低32位则代表了每代Leader中事务的唯一性。

zab节点的三种状态:

  • following:服从leader的命令
  • leading: 负载协调事务
  • election/looking:选举状态

 

二、Zookeeper的数据模型和节点类型 【树结构/文件目录】

1、数据模型:在结构上和标准文件系统的非常相似,拥有一个层次的命名空间,都是采用树形层次结构,ZooKeeper树中的每个节点被称为—Znode。和文件系统的目录树一样,ZooKeeper树中的每个节点可以拥有子节点。

不同之处:

  • Znode兼具文件和目录两种特点,既像文件一样维护着数据、元信息、ACL、时间戳等数据结构,又像目录一样可以作为路径标识的一部分,并可以具有子Znode。用户对Znode具有增删改查的操作(权限允许的情况下)
  • Znode具有原子性操作,读操作将获取与节点相关的所有数据,写操作也将替换掉节点的所有数据。
  • Znode存储数据大小有限制,Zookeeper虽然可以关联一些数据,但并不能存储太大的数据,通常以KB为大小单位。ZK的服务器和客户端都被设计为严格检查并限制每个Znode的数据大小至多1M,当时常规使用中应该远小于此值。
  • Znode通过路径引用,如同Unix中的文件路径。

每个Znode由3部分组成

stat:此为状态信息,描述该Znode的版本,权限等信息

data:与该Znode关联Znode关联的数据

children:该Znode下的子节点

2、节点类型

Znode有两种,分别为临时节点和永久节点。节点的类型在创建时即被确定,并且不能改变。

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

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

Znode还有一个序列化的特性,如果创建的时候指定的话,该Znode的名字后面会自动追加一个不断增加的序列号。序列号对于此节点的父节点来说是唯一的,这样便会记录每个子节点创建的先后顺序。它的格式为“%10d”(10位数字,没有数值的数位用0补充,例如“0000000001”)。

 

三、简述ZK的命名服务、配置管理、集群管理

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

配置管理:实际项目中,经常使用.properties或者xml需要配置很多信息,如数据库连接信息、fps地址端口等。程序分布式部署时,如果把程序的这些配置信息保存在zk的znode节点下,当你需要修改配置、即znode会发送变化时,可以通过改变zk中某个目录节点的内容,利用watch通知给各个客户端,从而更改配置。

集群管理:集群管理包括集群监控和集群控制,就是监控集群机器的状态,剔除机器和加入机器。zookeeper可以方便集群机器的管理,它可以实时监控znode节点的变化,一旦发现有机器挂了,该机器会与zk断开链接,对应的临时目录节点会被删除,其他所有机器都收到通知,新机器加入也类似。

 

四、Zookeeper watch机制的原理与实现

因为ZK有watch机制,可以随时发现一些数据的变化,从而达到数据的及时性。

ZK的所有读操作都可以设置watch监视点:getData、getChildren、exists。写操作则是不能设置监视点的。

监视有两种类型:数据监视点和子节点监视点。创建、删除或者设置znode都会触发这些监视点。exists,getData 可以设置监视点。getChildren 可以设置子节点变化。

而可能监测的事件类型有: NodeCreated, NodeDataChanged, NodeDeleted, NodeChildrenChanged.

ZK可以做到,只要数据一发生变化,就会通知相应地注册了监听的客户端,那么其实现原理如下:

1. 客户端注册Watcher到服务端;
2. 服务端发生数据变更;
3. 服务端通知客户端数据变更;
4. 客户端回调Watcher处理变更应对逻辑;

 

五、ZK与Eureka的区别

SpringCloud和Dubbo都支持多种注册中心,目前主流的架构SpringCloud用Eureka较多,Dubbo则以Zookeeper为主。

1、从集群设计来看:Eureka集群各节点平等,没有主从关系,因此可能出现数据不一致的情况;ZK为了满足一致性,必须包含主从关系,一主多从。集群无主机点时不对外提供服务。

ZK:当主节点因为网络故障与其他的节点失去联系时,剩余的节点会重新选举Leader,但是选举Leader的过程中比较耗时,30s-120s,并且选举的期间整个集群不可用。这就导致选举期间服务不可用。

Eureka:各节点是平等的,几个节点挂掉不会影响正常的节点工作,剩余的节点依然可以提供注册和查询服务。当Eureka的客户端在向某个Eureka注册时如果发现失败,会自动切换到其他的节点,只要有一台Eureka还在,就能保证注册服务可用(保证了可用性),只是不能保证强一致性,可能查到的信息不是最新的。除此之外,Eureka还有自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:

  • Eureka不再从注册列表中溢出因为长时间没有心跳而应该过期的服务。
  • Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点依然可用)
  • 当网络稳定时,当前实例新的注册信息会被同步到其他节点中。

2、CAP原则来看:Zookeeper保证的是CP,Eureka保证的是AP。

3、服务拉取方式来看:Eureka采用的是服务主动拉取策略,消费者按照固定的频率(默认30s)去Eureka拉取服务并缓存到本地;ZK中的消费者首次启动到ZK订阅自己需要的服务信息,并缓存在本地。然后监听服务列表变化,以后服务变更ZK会推送给消费者。

因此,Eureka可以很好的应对因为网络故障而导致部分节点失去联系的情况,但是ZK则不行,遇到网络故障的时候整个注册服务瘫痪。

 

posted @ 2022-01-17 21:18  娜梓  阅读(54)  评论(0编辑  收藏  举报