引用官方的说法:“Zookeeper是一个高性能,分布式的,开源分布式应用协调服务。它提供了简单原始的功能,分布式应用能够基于它实现更高级 的服务。它被设计为易于编程,使用文件系统目录树做为数据模型。服务端跑在java上,提供java和C的客户端 API”。java
集群服务,统一命名服务,分布式配置管理,分布式消息队列,分布式锁,分布式通知协调等。node
Leader/Follower算法
ZooKeeper须要在全部的服务(能够理解为服务器)中选举出一个Leader,而后让这个Leader来负责管理集群。此时,集群中的其它服务器则成为此Leader的Follower。而且,当Leader故障的时候,须要ZooKeeper可以快速地在Follower中选举出下一个Leader。编程
Observer服务器
Observer是zk集群的另外一个角色, observer的行为在大多数状况下与follower彻底一致, 可是他们不参加选举和投票, 而仅仅接受(observing)选举和投票的结果.数据结构
Zookeeper逻辑图以下:分布式
如上图所示,假设搭建了一个5台server的集群,5台机器根据选举算法,选出一个leader,其余节点就是follower。性能
选举好leader后会和每一个server创建长链接ui
修改操做:当某个节点收到修改操做时,就会将请求转发给leader,leader有处理机制,修改后同步到每个follower。设计
zookeeper集群搭建完成就能够启动客户端,客户端能够链接除leader外的全部节点,创建长链接,客户端任何修改信息都会同步到server上,由leader同步到各个节点
选举:当leader挂掉后就会选举一个新的leader,而后再从新创建链接。完成一次选举大概须要200ms。
ZNode
zookeeper目录树中每个节点对应一个Znode。每一个Znode维护着一个属性结构,它包含着版本号(dataVersion),时间戳(ctime,mtime)等状态信息。ZooKeeper正是使用节点的这些特性来实现它的某些特定功能。每当Znode的数据改变时,他相应的版本号将会增长。每当客户端检索数据时,它将同时检索数据的版本号。而且若是一个客户端执行了某个节点的更新或删除操做,他也必须提供要被操做的数据版本号。若是所提供的数据版本号与实际不匹配,那么这个操做将会失败。
Session
Client与ZooKeeper之间的通讯,须要建立一个Session,这个Session会有一个超时时间。由于ZooKeeper集群会把Client的Session信息持久化,因此在Session没超时以前,Client与ZooKeeper Server的链接能够在各个ZooKeeper Server之间透明地移动。
在实际的应用中,若是Client与Server之间的通讯足够频繁,Session的维护就不须要其它额外的消息了。不然,ZooKeeper Client会每t/3 ms发一次心跳给Server,若是Client 2t/3 ms没收到来自Server的心跳回应,就会换到一个新的ZooKeeper Server上。这里t是用户配置的Session的超时时间。
Watcher
ZooKeeper支持一种Watch操做,Client能够在某个ZNode上设置一个Watcher,来Watch该ZNode上的变化。若是该ZNode上有相应的变化,就会触发这个Watcher,把相应的事件通知给设置Watcher的Client。
zookeeper维护一个相似文件系统的数据结构
Zookeeper表现为一个分层的文件系统目录树结构(不一样于文件系统的是,节点能够有本身的数据,而文件系统中的目录节点只有子节点)。
由根目录和各个子目录组成,每个子目录称为znode,znode相似文件夹,可是znode能够存储数据
znode分为4中类型
1.持久化节点
所谓持久节点,是指在节点建立后,就一直存在,直到有删除操做来主动清除这个节点——不会由于建立该节点的客户端会话失效而消失。
2.持久化顺序节点
这类节点的基本特性和上面的节点类型是一致的。额外的特性是,在ZK中,每一个父节点会为他的第一级子节点维护一份时序,会记录每一个子节点建立的前后顺序。基于这个特性,在建立子节点的时候,能够设置这个属性,那么在建立节点过程当中,ZK会自动为给定节点名加上一个数字后缀,做为新的节点名。这个数字后缀的范围是整型的最大值。
3.临时节点
这类节点的基本特性和上面的节点类型是一致的。额外的特性是,在ZK中,每一个父节点会为他的第一级子节点维护一份时序,会记录每一个子节点建立的前后顺序。基于这个特性,在建立子节点的时候,能够设置这个属性,那么在建立节点过程当中,ZK会自动为给定节点名加上一个数字后缀,做为新的节点名。这个数字后缀的范围是整型的最大值。
4.临时顺序节点
能够用来实现分布式锁
客户端调用create()方法建立名为“_locknode_/guid-lock-”的节点,须要注意的是,这里节点的建立类型须要设置为EPHEMERAL_SEQUENTIAL。
客户端调用getChildren(“_locknode_”)方法来获取全部已经建立的子节点,注意,这里不注册任何Watcher。
客户端获取到全部子节点path以后,若是发现本身在步骤1中建立的节点序号最小,那么就认为这个客户端得到了锁。
若是在步骤3中发现本身并不是全部子节点中最小的,说明本身尚未获取到锁。此时客户端须要找到比本身小的那个节点,而后对其调用exist()方法,同时注册事件监听。
以后当这个被关注的节点被移除了,客户端会收到相应的通知。这个时候客户端须要再次调用getChildren(“_locknode_”)方法来获取全部已经建立的子节点,确保本身确实是最小的节点了,而后进入步骤3。
ZooKeeper支持一种Watch操做,Client能够在某个ZNode上设置一个Watcher,来Watch该ZNode上的变化。若是该ZNode上有相应的变化,就会触发这个Watcher,把相应的事件通知给设置Watcher的Client。须要注意的是,ZooKeeper中的Watcher是一次性的,即触发一次就会被取消,若是想继续Watch的话,须要客户端从新设置Watcher。这个跟epoll里的oneshot模式有点相似。