1.ZooKeeper是什么
简单来说,她是一个分布式的,开放源码的分布式应用程序协调服务
具体来说,他可以做如下事情:
- 分布式配置管理:ZooKeeper可以存储配置信息,应用程序可以动态读取配置信息。
- 分布式同步:ZooKeeper可以协调各个节点的同步,确保数据的一致性。
- 命名服务:ZooKeeper可以作为一个命名服务,应用程序可以通过名字来找到所需的服务。
- 集群管理:ZooKeeper可以用来管理分布式集群,协调各个节点的加入和退出。
- Master选举:ZooKeeper可以用来实现Master选举,选择一个节点作为Master节点。
- 分布式协调服务:Zookeeper提供了一些分布式协调服务,如分布式锁、唯一标识生成等,帮助系统中的各个组件之间进行协调。
- 服务注册和发现:Zookeeper可以用于注册和发现系统中的服务,简化服务的部署和更新。
- 负载均衡:Zookeeper可以用于动态地对请求进行负载均衡,以提高系统的可用性
2.Zookeeper的数据结构是怎么样的?
-
数据模型
-
数据是以目录结构的形式存储的
-
每一个存储数据的节点都叫做Znode,每个Znode都有一个唯一的路径标识
-
每一个节点都可以可有子节点(临时节点除外)
-
节点中可以存储数据和状态信息
-
每个Znode上可以配置监视器(watcher),用于监听节点中的数据变化。
-
节点不支持部分读写,而是一次性完整读写。
-
每个znode被创建时都会带有一个ACL列表,用于决定谁可以对它执行何种操作
-
-
-
节点类型
-
Znode有四种类型
-
PERSISTENT(持久节点)
- 在节点创建后,就一直存在,直到有删除操作来主动清除这个节点------不会因为创建该节点的客户端会话失效而消失。
-
PERSISTENT_SEQUENTIAL(持久的连续节点)
-
在ZooKeeper中,每个父节点会为他的第一级子节点维护一份时序,会记录每个子节点创建的先后顺序。
-
在创建节点过程中,ZooKeeper会自动为给定节点名加上一个数字后缀,作为新的节点名(序列号会自动递增)。这个数字后缀的范围是整型的最大值。
-
-
EPHEMERAL(临时节点)
- 临时节点的生命周期和客户端会话绑定。也就是说,如果客户端会话失效 ,那么这个节点就会自动被清除掉
-
EPHEMERAL_SEQUENTIAL(临时的连续节点)
- 临时节点的生命周期和客户端会话绑定。注意创建的节点会自动加上编号(序列号会自动递增)。
-
-
3.Zookeeper集群中的角色有哪些?有什么区别?
-
ZK中主要有以下角色:
-
领导者(leader)
-
负责进行投票的发起和决议,更新系统状态。
-
为客户端提供读和写服务。
-
-
跟随者(follower)
-
在选主过程中参与投票。
-
为客户端提供读服务,转发写请求。
-
-
观察者(observer)
-
可以接受客户端连接处理读请求,将写请求转发给leader
-
但observer不参加投票过程,只同步leader的状态
-
observer的目的是为了扩展系统,提高zookeeper集群的读性能
- Observer支持更多的客户端连接提高了zookeeper读性能的同时又不影响zookeeper的写性能
-
-
客户端(client)
- 请求发起方
-
4.Zookeeper是CP的还是AP的?
-
ZooKeeper职责
-
ZooKeeper作为分布式协调服务,它的职责是保证数据在其管辖下的所有服务之间保持同步、一致
-
所以会牺牲可用性,会丢弃一些请求,消费者程序需要重新请求才能获得结果。
-
所以是cp的
-
-
cp的体现
-
zookeeper的写操作是要经过半数以上的Follower确认才能够写成功的。那么当zookeeper集群中的节点越多时,zookeeper的写性能就越差。如果集群中的存活节点数低于总结点数的一半,那么整个集群将无法接受新的写 请求。
-
在 ZK 的 master 选举过程中,在新的Master被选举出来之前,整个集群也无法接受新的写请求。
- 如果 ZooKeeper下所有节点都断开了,或者集群中出现了网络分割的故障,那么ZooKeeper 会将它们都从自己管理范围中剔除出去,外界就不能访问到这些节点了,即便这些节点本身是"健康"的,可以正常提供服务的;
-
5.Zookeeper是选举机制是怎样的?
-
提名和投票
-
在提名过程中,所有的投票者都遵守一个原则,那就是遇强投强。
-
在Zookeeper中,通过数据是否足够新来判断这个节点是不是够强,在 Zookeeper 中以事务id(zxid)来标识数据的新旧程度,节点的zxid越大代表这个节点的数据越新,也就代表这个节点能力越强。
-
那么在投票过程中,节点首先会认为自己是最强的,所以他会在投票时先投自己一票,然后把自己的投票信息广播出去 ,这里面包含了zxid和sid,zxid就是自己的事务ID,sid就是标识出自己是谁的唯一标识。
-
这样集群中的节点们就会不断收到别人发过来的投票结果 ,然后这个节点就会拿别人的zxid和自己的zxid进行比较,如果别人的zxid更大, 说明他的数据更新,那么就会重新投票,把zxid和sid都换成别人的信息再发出去。
-
-
选举过程:如果一个候选者获得了大多数节点投票,它就会成为新的Leader,否则,所有节点会继续下一个选举周期
- 选举过程分为多个轮次,每个轮次被称为一个"选举周期"。在每个选举周期中,节点根据投票数来选择新的Leader候选者。如果一个候选者获得了大多数节点(超过半数)的投票,那么它就会成为新的Leader。否则,没有候选者能够获得足够的投票,那么这个选举周期失败,所有节点会继续下一个选举周期
-
-
6.如何用Zookeeper实现分布式锁?
-
基于zookeeper临时有序节点可以实现的分布式锁。
-
客户端首先连接到 ZooKeeper 集群
-
客户端在特定路径下创建临时有序节点:
- 例如,如果路径为
/lock
,那么客户端创建的节点可能是/lock/lock-00000001
,下一个创建的节点可能是/lock/lock-00000002
,依此类推。
- 例如,如果路径为
-
通过序号获取锁:
-
客户端获取
/lock
目录下所有子节点,并按序号排序。 -
检查自己创建的节点是否是序号最小的节点。如果是,则获取锁。
-
-
等待锁:
-
如果当前客户端的节点不是序号最小的节点,那么找到比自己序号小的节点,设置监听器等待它被删除。
-
当上一个节点被删除时,ZooKeeper 会通知客户端,此时客户端重新检查自己是否成为了序号最小的节点。
-
-
释放锁:
- 完成任务后,删除自己创建的临时节点,从而释放锁
-
7.Zookeeper是如何保证创建的节点是唯一的?
第6点说到分布式锁通过Zookeeper创建节点实现的,那么如何保证创建的节点是唯一的
-
Zookeeper通过两个手段来保证节点创建的唯一性:
-
所有的写请求都会由Leader进行,即使是请求到Follower节点,也会被转发到Leader节点上执行
-
通过加锁(synchronized)和CAS(ConcurrentHashMap)操作,保证了并发情况下只有一个线程可以添加节点成功。
- 先是通过synchronized锁,将父节点锁住,然后再在锁里面判断是否已经存在节点,如果已存在,直接抛异常,如果不存在,则向维护了节点的map------NodeHashMap中添加当前节点。
-
8.Zookeeper的watch机制是如何工作的?
-
watch机制是什么
- 能够让应用程序监听Zookeeper上节点的变化,从而及时做出响应。
-
Zookeeper的watch机制是如何工作的?
-
客户端连接到Zookeeper服务端,客户端创建一个ZkWatcherManager实例,用于管理客户端中所有的watcher。
-
当客户端想要监控某个znode节点时,它可以调用ZkWatcherManager中的方法创建watcher并将其注册到客户端中。客户端将watcher的信息发送到Zookeeper服务端。
-
Zookeeper服务端接收到客户端发送的watcher信息后,会将该watcher信息交给WatchManager处理。WatchManager会将该watcher注册到相应的znode节点上,并将watcher相关的信息保存在内存中。
-
当znode节点发生变化时,WatchManager会通知Zookeeper Server
-
Zookeeper Server会根据变化类型通知相应的客户端,告知它们发生了哪些变化。
-
当客户端接收到Zookeeper Server的通知后,ZkWatcherManager会根据watcher的类型 (data watcher或child watcher)来触发相应的事件处理方法,例如data watcher会触发processDataChanged()方法,child watcher会触发processChildChanged()方法等。
-