首先我们都知道Zookeeper是一个分布式组件。就像其官网描述的那样:
官网地址:Apache ZooKeeper
其实zookeeper的应用场景有很多。这里只是简单列举几个:
同时Zookeeper 在 Kafka 架构中扮演着关键角色,提供了稳定的协调和元数据管理机制,使 Kafka 能够高效且可靠地处理大规模数据流。随着 Kafka 的新版本发展,对 Zookeeper 的依赖正在减少,但在许多部署中它仍然是一个关键组件。
我们如果在面试过程中,如果要是聊到Zookeeper,同时你有很懂Kafka,那么恭喜你就可以由此为切入点,然后开始大杀特杀了。
要是聊到Zookeeper的数据结构,那么不得不说Zookeeper的以下几个概念:
目录树结构:但是没有文件和文件夹的概念,是节点的概念。
节点存储的数据很小(约1M),存储的数据很小原因是要保证对外协调工作的一个速度要很快
二进制安全的:外界客户端需要给字节数组,所以在使用zookeeper的时候要约定好编解码器,序列和反序列化。
zk的数据状态在内存,用磁盘保存日志
一直所提到的Znode就是Zookeeper的节点。Znode分为以下4种类型:
注意:Znode的类型在创建时确定后不能进行修改。同时节点中可以存储数据,还存储了状态信息。
所谓Zookeeper的临时节点就是它的生命周期和客户端的会话是绑定的。简而言之:如果客户端会话失败,那么这个节点也就会自动被清除掉。
利用session做分布式锁,不再向redis分布式锁那样需要设置过期时间,同时死锁、锁超时等问题也就不会存在,也不需要在程序占用利用多线程去维护(一个线程去库,一个线程监控,取回来更新锁时间)。但是这样也并不是完美的,因为会产生羊群效应。所以如果使用ZK做分布式锁,最好采用临时顺序节点。这样可以避免羊群效应的发生。
假设使用临时节点做分布式锁,当客户端断开连接的时候,我们就需要监听这个临时节点的变化。只有监听到临时节点的变化方可避免死锁的问题。但是如果所有服务都去监听一个节点的,节点的释放也会通知所有的服务器,如果是900个服务器呢?这对服务器是很大的一个挑战,一个释放的消息,就好像一个牧羊犬进入了羊群,大家都四散而开,随时可能干掉机器,会占用服务资源,网络带宽等等。这就是羊群效应
注意:上面提到过的。临时节点不能有子节点
所谓Zookeeper的持久节点,指的就是:在创建节点后,直到有删除操作来主动清除这个节点,该节点是不会随着客户端会话的失效而消失。
所谓Zookeeper的临时顺序节点,就是在创建的节点会自动加上编号,它也会随着客户端会话的失效而消失。
其实Zookeeper的持久顺序节点它的特性就是持久类型的节点的基本特性是一样的,只不过增加了一个在创建节点是自动添加上编号。
Zookeeper中,每个父节点会为它的第一级子节点维护一份时序,会记录每个子节点创建的先后顺序。基于这个特性,在创建子节点的时候,可以设置这个属性,那么在创建节点过程中,Zookeeper会自动为给定的节点名加上一个数字后缀,作为新的节点名。这个数字后缀的范围是整型的最大值。
ACL就是访问控制列表。Access Control List
其特性如下:
ACL 权限控制,使用:scheme:id:perm
来标识,主要涵盖 3 个方面:
所谓的ACL就是每个Znode创建时都会有一个列表,用于决定谁可以对它执行何种操作。
Watcher在Zookeeper中是一个核心的功能,Watcher可以监控目录节点变化以及目录的变化。一旦这些状态发生变动,服务器就会通知所有设置在这个目录节点上的Watcher,从而每个客户端可以很快知道它所关注的目录节点的状态发生了变化,以便做出对应的处理。
exists
、getChildren
、getData
create
、delete
、setData
Zookeeper中的Watch整体思路很像是分布式环境下的观察者模式。
ZKWatchManager
中对应的Watch Map,在Map中注册相关的Watch。注意:getWatch的过程没有加锁,注册Watch时通过synchronized关键字来保证原子性。因为只有写操作下才有可能出现线程安全问题。
WatchManager
中。FinalRequestProcessor#processRequest
方法实现的。我们可以把类似数据库配置信息存储在Zookeeper数据节点中。服务器集群客户端对该节点添加Watch事件监控,当即群众的服务启动时,会读取该节点数据获取数据配置信息。而当该节点数据发生变化时,【Zookeeper服务器会发送Watch事件给各个客户端(推)】,集群中的客户端在接收到该通知后,【重新读取节点中的数据库配置信息(拉)】
Dubbo项目中采用Zookeeper作为注册中心(CP),原理和配置中心类似,其与Eurka的AP设计形成了鲜明对比。
Zookeeper主要通过两方面来保证节点创建的唯一性:
主要有以下角色:
Paxos算法时莱斯利·兰伯特于1990年提出的一种基于消息传递且具有高度容错性的一致性算法。在基于传递通信模型的分布式系统,不可避免地会发生以下错误:进程可能会慢、被杀死或重启,消息可能会延迟、丢失、重复。Paxos算法可解决分布式系统中如何就某个值达成一致,保证不论发生以上任何异常,都不会破坏一致性。是至今为止唯一的分布式一致性算法,Paxos前提是没有拜占庭将军问题,就是Paxos只有在一个可信的计算环境中才能成立。
ZAB协议是为分布式协调服务zookeeper专门设计地一种支持崩溃恢复地原子广播协议,是Zookeeper保证数据一致性地核心算法。ZAB借鉴了Paxos算法,但又不像Paxos算法那样,是一种通用的分布式一致性算法,相比Paxos,ZAB最大的特点就是保证强一致性。
ZAB协议包括两种基本的模式:崩溃恢复和消息广播。Zookeeper的核心是通过ZAB协议保证了各个Server之间的同步。当服务启动或者在Leader崩溃后,ZAB就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和Leader的状态同步之后,恢复模式就结束了。状态同步保证了Leader和Server具有相同的系统状态。
ZAB协议提交事务提案的过程跟Paxos有点类似,都是由Leader发送给下面的Follower,让Follower进行投票表决,都是超过半数以上才会通过。但是ZAB协议比Paxos多的是崩溃恢复模式,也就是Leader崩溃时,能够自我恢复。所以ZAB协议跟Paxos算法最主要的区别就是:两个设计的目标不同,ZAB协议主要用于构建一个高可用的分布式数据的主备系统,因为有崩溃恢复,Leader崩溃能够重新选举,达到一个高可用的目的。而Paxos算法目的在于构建一个分布式数据一致性系统,强调的是数据的一致性,当Proposer提议者崩溃时不能自我恢复,从而丢失高可用的功能
参考:https://www.cnblogs.com/semi-sub/p/13243354.html
过半通过的数据才是真数据,你见到的可用的Zxid 选举的过程
推选值。先比较zXid,再myid
好了,本章节到此告一段落。希望对你有所帮助,祝学习顺利。