一、zookeeper是什么
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于Zookeeper实现诸如数据发布/订阅,负载均衡,命名服务,分布式协调/通知,集群管理,Master选举,分布式锁和分布式队列等功能。
zookeeper是一个分布式服务框架,是Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。可以这样来理解zookeeper,即zookeeper=文件系统+监听通知机制。Zookeeper底层其实提供了两个功能,即管理用户程序提交的数据、为用户程序提供节点监听服务。
1、文件系统
Zookeeper维护一个类似文件系统的数据结构,如下图所示:
每个子目录项如 NameService 都被称作为 znode(目录节点),和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。
在Zookeeper中,znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据。如果在创建znode时Flag设置为EPHEMERAL(临时节点),那么当创建这个znode的节点和Zookeeper失去连接后,这个znode将被Zookeeper删除。Zookeeper使用Watcher察觉事件信息,当客户端接收到事件信息,比如连接超时、节点数据改变、子节点改变,就可以调用相应的行为来进行处理。
2、监听通知机制
客户端注册监听它,关心的是目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。
二、zookeeper设计理念或目标
ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户使用。它包含一个简单的原语集,提供Java和C的接口。ZooKeeper代码版本中,提供了分布式独享锁、选举、队列的接口,代码在$zookeeper_homesrc ecipes。其中分布锁和队列有Java和C两个版本,选举只有Java版本。
三、zookeeper特点特性
Zookeeper是简单的、富有表现力的、高可用性的、松耦合的,并且它还是一个资源库。
1、简单的数据模型
ZooKeeper允许分布式进程通过共享的层次结构命名空间进行相互协调,这与标准文件系统类似。 名称空间由 ZooKeeper中的数据寄存器组成——称为znode,这些类似于文件和目录。
2、顺序一致性
对于来自客户端的每个更新请求,Zookeeper都会分配一个全局唯一的递增编号,这个编号反应了所有事务操作的先后顺序,应用程序可以使用Zookeeper这个特性来实现更高层次的同步原语,这个编号也叫时间戳——zxid。
3、原子性
所有事务处理结果在整个集群中所有机器上的应用情况是一致的,即要么整个集群中所有的机器都成功应用了某一个事务,要么都没有应用,不存在中间的状态。
4、单一系统映像
无论客户端连到哪一个zookeeper服务器,其看到的服务器数据模型都是一致的。
5、可靠性
一旦一次更改请求被应用,更改结果就会被持久化,直到被下一次更改覆盖。
6、可构建集群
为了保证高可用,最好是以集群形式部署Zookeeper,这样只要集群中大部分机器是可用的,那么zookeeper本身仍然可用。
7、高性能
Zookeeper是高性能的,在读多于写的应用程序中尤其的高性能,因为写会导致所有服务器同步状态。
8、独立性:各个Client之间互不干预。
9、Zookeeper将数据保存在内存中,保证了高吞吐和低延迟,但内存限制了存储的容量,从而导致Znode中存储的数据量较小。
四、zookeeper的使用场景
为什么需要zookeeper?
1、大部分分布式应用需要一个主控、协调器或控制器来管理物理分布的子进程(如资源、任务分配等)
2、目前大部分应用需要开发私有的协调程序,缺乏一个通用的机制,虽然协调程序在反复的编写但难以形成通用、伸缩性好的协调器。
3、ZooKeeper正好能满足以上要求,它提供通用的分布式锁服务,用以协调分布式应用。
Zookeeper一个最常用的使用场景就是用于担任生产者和服务消费者的注册中心,提供发布/订阅服务。服务生产者将自己提供的服务注册到Zookeeper中心,服务消费者在进行服务调用的时候先到Zookeeper中查找服务,获取到服务生产者的详细信息之后,再去调用服务生产者的内容与数据来进行消费。
如在Dubbo中,Zookeeper就担任注册中心的角色。如下图所示:
在使用Zookeeper的时候,最好使用集群版Zookeeper,而且最好使用集群版服务器构成Zookeeper集群。Zookeeper容错中,当宕掉几个Zookeeper服务器后,剩下的个数必须大于宕掉个数,整个Zookeeper才能依然使用。假如集群中有n台Zookeeper服务器,那么也就是剩下的服务器数必须大于n/2,所以当n是奇数的时候则宕掉的最多为(n-1)/2,当n为偶数时,宕掉的最多为n/2,而剩下的最多的数量都是一样的。比如假如我们有3台,那么最大允许宕掉1台zookeeper服务器,如果我们有4台的的时候也同样只允许宕掉1台。假如我们有5台,那么最大允许宕掉2台zookeeper服务器,如果我们有6台的的时候也同样只允许宕掉2台。所以使用奇数台zookeeper就够了。
除了作为服务注册中心之外,zookeeper还可以实现诸如分布式应用配置管理、统一命名服务、状态同步服务、集群管理等功能。总之,zookeeper的能提供的功能非常的强大。
例如使用zookeeper来做分布式应用配置管理:
假设我们的程序是分布式部署在多台机器上,如果我们要改变程序的配置文件,需要逐台机器去修改,非常麻烦,现在把这些配置全部放到zookeeper上去,保存在zookeeper的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到zookeeper的通知,然后从zookeeper获取最新的配置信息应用到系统中,如下图所示:
五、zookeeper重要基础概念
1、Seesion
Session是指Zookeeper服务器与客户端会话。在Zookeeper中,一个客户端连接是指客户端和服务器之间的一个TCP长连接。客户端启动的时候,首先会与服务器建立一个TCP连接,从第一次连接建立开始,客户端会话的生命周期就开始了。通过这个连接,客户端能够通过心跳检测与服务器保持有效的会话,也能够向Zookeeper服务器发送请求并接受响应,同时还能够通过该连接接收来自服务器的Watch事件通知。
Session的sessionTimeout可以设置客户端会话的超时时间。由于服务压力大,网络故障或者客户端主动断开连接等各种原因导致客户端连接断开时,只要在sessionTimeout规定的时间内能够重新连接上集群中任意一台服务器,那么之前创建的会话仍然有效。在为客户端创建会话之前,服务端首先会为每个客户端都分配一个sissionID由于sessionID是Zookeeper会话的一个重要标识,许多与会话相关的运行机制都是基于sessionID的,因此,无论是哪台服务器为客户端分配的sessionID,都需要保证全局唯一。
2、ZNode
在Zookeeper中,节点分为两类,第一类是指构成集群的机器,称为机器节点,第二类是指数据模型中的数据单元,称为数据节点——ZNode。Zookeeper将所有数据存储在内存中,数据模型是一棵树,由/进行分割的路径,就是一个Znode,每个节点上都会保存自己的数据内容,同时还会保存一系列属性信息。
有四种类型的znode:
(1)PERSISTENT——持久化目录节点:客户端与zookeeper断开连接后,该节点依旧存在。
(2)PERSISTENT_SEQUENTIAL——持久化顺序编号目录节点:客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号。
(3)EPHEMERAL——临时目录节点:客户端与zookeeper断开连接后,该节点被删除。
(4)EPHEMERAL——SEQUENTIAL-临时顺序编号目录节点:客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号。
3、version
Zookeeper的每个ZNode上都会存储数据,对应于每个ZNode,Zookeeper都会为其维护一个State数据结构,Stat中记录了这个ZNode的三个数据版本,分别是Version——当前ZNode的版本,cversion——当前ZNode子节点的版本,aversion——当前ZNode的ACL版本。
4、Watcher
Watcher——事件监听器,是Zookeeper中一个很重要的特性。Zookeeper允许用于在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,Zookeeper服务端会将事件通知到感兴趣的客户端上去,该机制是Zookeeper实现分布式协调服务的重要特性。
5、ACL
Zookeeper采用ACL策略来进行权限控制,权限分为:
(1)CREATE:创建子节点的权限。
(2)READ:获取节点数据和子节点列表的权限。
(3)WRITE:更新节点数据的权限。
(4)DELETE:删除子节点的权限。
(5)ADMIN:设置节点的ACL权限。
其中CREATE和DELETE这两种权限都是针对子节点的控制权限。
六、zookeeper的执行流程
ZooKeeper的基本执行流程:1、选举Leader,2、同步数据。
Zookeeper leader选举过程:
通俗一点的解释:
(1)A提案说,我要选自己,B你同意吗?C你同意吗?B说,我同意选A;C说,我同意选A。(注 意,这里超过半数了,其实在现实世界选举已经成功了。但是计算机世界是很严格,另外要 理解算法,要继续模拟下去。)
(2)接着B提案说,我要选自己,A你同意吗;A说,我已经超半数同意当选,你的提案无效;C 说,A已经超半数同意当选,B提案无效。 接着C提案说,我要选自己,A你同意吗;A说,我已经超半数同意当选,你的提案无效;B 说,A已经超半数同意当选,C的提案无效。
(3)选举已经产生了Leader,后面的都是follower,只能服从Leader的命令。而且这里还有个小细节,其实就是谁先启动谁当头。
稍微正经一点的解释:
(1)Leader election-选举阶段,节点在一开始都处于选举节点,只要有一个节点得到超半数节点的票数,它就可以当选准leader。
(2)Discovery-发现阶段,follower和准Leader进行通信,同步follower最近接受的事务提议。
(3)Synchronization-同步阶段,利用Leader在前一阶段获取到的最新提议历史,同步集群中所有副本,同步完成后,准Leader才成为真正的Leader。
(4)Broadcast-广播阶段,Zookeeper集群正式对外提供事务服务,并且Leader可以进行消息广播,同时如果有新节点加入,还需要对新节点进行同步。
在Zookeeper中分为Leader,Follower,Observer三种角色,如下图所示:
Zookeeper集群中所有的机器通过一个Leader选举过程来选定一台Leader机器,Leader既可以为客户端提供写服务又能提供读服务。Follower和Observer都只提供读服务。Follower和Observer唯一的区别是Observer不参与Leader的选举过程,也不参与写操作的“过半写成功”策略,因此Observer机器可以在不影响写性能的情况下提升集群的读性能。当Leader服务器出现网络中断、崩溃退出或者重启等异常情况时,ZAB协议就会进入恢复模式并选举产生新的Leader服务器。
七、ZooKeeper的ZAB协议和Paxos算法
ZooKeeper是以Fast Paxos算法为基础的,Paxos算法存在活锁的问题,即当有多个proposer交错提交时,有可能互相排斥导致没有一个proposer能提交成功,而Fast Paxos作了一些优化,通过选举产生一个leader (领导者),只有leader才能提交proposer,具体算法可见Fast Paxos。因此,要想更加深入的学习ZooKeeper需要对Fast Paxos有所了解。
1、ZAB协议、Paxos算法
Paxos算法应该可以说是ZooKeeper的灵魂了。但ZooKeeper并没有完全采用Paxos算法 ,而是使用ZAB协议作为其保证数据一致性的核心算法。另外在ZooKeeper的官方文档中也指出,ZAB协议并不像Paxos算法那样,是一种通用的分布式一致性算法,它是一种特别为Zookeeper设计的崩溃可恢复的原子消息广播算法。
2、ZAB协议介绍
ZAB(ZooKeeper Atomic Broadcast 原子广播) 协议是为分布式协调服务ZooKeeper专门设计的一种支持崩溃恢复的原子广播协议。 在ZooKeeper中,主要依赖ZAB协议来实现分布式数据一致性,基于该协议它实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。
3、ZAB协议两种基本的模式:崩溃恢复和消息广播
ZAB协议包括两种基本的模式,即崩溃恢复和消息广播。当整个服务框架在启动过程中,或是当Leader服务器出现网络中断、崩溃退出与重启等异常情况时,ZAB协议就会进入恢复模式并选举产生新的Leader服务器。当选举产生了新的Leader服务器,同时集群中已经有过半的机器与该Leader服务器完成了状态同步之后,ZAB协议就会退出恢复模式。其中所谓的状态同步是指数据同步,用来保证集群中存在过半的机器能够和Leader服务器的数据状态保持一致。
当集群中已经有过半的Follower服务器完成了和Leader服务器的状态同步,那么整个服务框架就可以进入消息广播模式了。当一台同样遵守ZAB协议的服务器启动后加入到集群中时,如果此时集群中已经存在一个Leader服务器在负责进行消息广播,那么新加入的服务器就会自觉地进入数据恢复模式:找到Leader所在的服务器,并与其进行数据同步,然后一起参与到消息广播流程中去。
正如上文介绍中所说的,ZooKeeper设计成只允许唯一的一个Leader服务器来进行事务请求的处理。Leader服务器在接收到客户端的事务请求后,会生成对应的事务提案并发起一轮广播协议,而如果集群中的其他机器接收到客户端的事务请求,那么这些非Leader服务器会首先将这个事务请求转发给Leader服务器。
八、参考资料
(1) https://baike.baidu.com/item/zookeeper/4836397?fr=aladdin
(2) https://www.jianshu.com/p/57913c3a7f0a
(3) https://blog.csdn.net/qq_18416057/article/details/54927189
(4) https://blog.csdn.net/java_66666/article/details/81015302
(5) https://zookeeper.apache.org/doc/r3.5.5/zookeeperOver.html (zookeeper官网)
(6) https://zhuanlan.zhihu.com/p/69114539?utm_source=wechat_session
(7) https://www.jianshu.com/p/e68c06a5d002
(8) https://www.cnblogs.com/ultranms/p/9585191.html (zookeeper到底是用来干嘛的)
(9) https://blog.csdn.net/weixin_44801979/article/details/90550579 (zookeeper用作注册中心原理)