Zookeeper是一个开源的分布式协调服务,由雅虎公司创建,是Google Chubby的开源实现,后来托管到Apache,于2010年11月正式成为Apache的顶级项目。 Zookeeper为分布式应用提供了高效且可靠的分布式协调服务,提供了如:数据发布与订阅、负载均衡、命名服务、分布式协调与通知、集群管理、Leader选举、分布式锁和分布式队列等功能。在解决分布式数据一致性方面,Zookeeper并没有直接采用Paxos算法,而是采用了一种被称为ZAB
的一致性协议。
从同一个客户端发起的事务请求,最终将会严格的按照其发起顺序被应用到Zookeeper中去。
所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致,也就是说,要么一个事务要么在集群中所有的集群处理成功,要么都没有成功,不会出现集群中的部分机器成功处理了该事务,而另一部分机器处理该事务失败。
无论客户端连接的是哪个Zookeeper服务器,其看到的服务端数据模型是一致的。
一旦服务端成功处理了一个事务,并完成对客户端的响应。那么该事务的服务端状态变更会一直保留下来,除非另一个事务对其进行了变更。
Zookeeper仅仅保证在一定时间内,客户端最终一定能够从服务端上读取到最新的数据状态。
Zookeeper致力于提供一个高性能、高可用,并且具有严格的顺序访问控制能力(主要是写操作的严格顺序性)的分布式协调服务。高性能使得Zookeeper能够应用于那些对系统吞吐有明确要求的大型分布式系统中,高可用使得分布式的单点问题得到很好的解决,而严格的顺序访问控制使得客户端能够基于Zookeeper实现一些复杂的同步原语。下面我们来具体看下Zookeeper的四个设计目标。
Zookeeper使得分布式程序能够通过一个共享、树形结构的名字空间来进行相互协调。
这里的树形结构的名字空间是指Zookeeper服务器内存中的一个数据模型,其由一系列被称为ZNode的数据节点组成。类似于一个文件系统,而ZNode之间的层级关系就像文件协调的目录结构。它和传统的磁盘文件系统不同的是,Zookeeper将全量的数据存储在内存中,以此来提供服务器吞吐、减少延迟。
一个Zookeeper集群通常由一组机器组成,一般3~5台机器就能组成一个可用的集群,如下图所示:
组成Zookeeper集群的每台机器都会在内存中维护当前的服务器状态,并且每台机器之间都互相保持着通信。只要集群中存在操作一般的集群能够正常工作就能够正常对外提供服务。
对于来自客户端的每个更新请求,Zookeeper都会分配一个全局唯一的递增编号,这个编号反映了所有事务操作的先后顺序。应用程序可以使用Zookeeper的这个特性来实现更高层次的同步原语。
由于Zookeeper将全量的数据存储在内存中,并且之间服务于客户端的所有非事务请求。因此它尤其适用于读操作为主的应用场景。
在Zookeeper中,没有沿用传统的Master/Slave概念,而是引入了Leader、Follower和Observer三种角色。Zookeeper集群中的所有机器通过Leader选举过程选定一台机器为Leader。
Leader服务器是整个Zookeeper集群工作机制的核心,其主要作用有:
Follower服务器是Zookeeper集群状态的跟随者,其主要工作如下:
Observer服务器充当了一个观察者的角色,观察Zookeeper集群的最新变化,并将这些状态同步过来。其主要工作如下:
处理客户端非事务请求,转发事务请求给Leader服务器。
不参与事务请求Proposal(提议)的投票。
不参与Leader选举投票。
Session是指客户端会话。在Zookeeper中,一个客户端连接是指客户端和服务器之间的一个TCP长连接。Zookeeper对外的服务端口默认是2181.客户端启动的时候,首先会与服务器建立一个TCP连接。从第一次连接建立开始,客户端会话的生命周期也开始了。通过这个连接,客户端能够通过心跳检测与服务器保持有效的会话,也能够向Zookeeper服务器发送请求并接受响应,同时还能够通过该链接接收来自服务器的Watch事件通知。Session的sessionTimeout
值用来设置一个客户端会话超时时间。当由于服务器压力太大、网络故障或者客户端主动断开连接等各种原因导致客户端连接断开时,只要在sessionTimeout
规定的时间内能够重新连接上集群中任意一台服务器,那么之前创建的会话仍然有效。
在Zookeeper中数据模型中的数据单元,我们称之为数据节点——ZNode
。Zookeeper将所有数据存储在内存中,数据模型是一棵树(ZNode Tree),由斜杆(/)进行分割的路径,就是一个ZNode
,例如/hbase/config
。每个ZNode上
都会保存自己的数据内容,同时还会保存一系列属性信息。
在Zookeeper中,ZNode
可以分为持久节点和临时节点两类。持久节点是指一定这个ZNode
被创建了,除非主动进行ZNode
的删除操作,否则这个ZNode
将一直保存在Zookeeper上。而临时节点就不一样了,它的生命周期和客户端会话绑定,一旦客户端会话失效,那么这个客户端创建的所有临时节点都会被移除。此外,Zookeeper还允许用户为每个节点添加一个特殊的属性:SEQUENTIAL
。一旦节点被标记上这个属性,那么这个节点创建的时候,Zookeeper会自动在其节点名后追加上一个整型数字。这个整型数字是由父节点维护的自增数字。
前面我们已经提到,Zookeeper的每个ZNode
上都会存储数据,对应于每个ZNode
,Zookeeper都会为其维护一个叫做Stat
的数据结构,Stat
中记录这个ZNode
的三个数据版本,分别是version
(当前ZNode的版本号),cversion
(当前ZNode子节点的版本)和aversion
(当前ZNode的ACL版本号)。
Watcher(事件监听器),是Zookeeper中的一个很重要的特性。Zookeeper允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,Zookeeper服务端会将事件通知到感兴趣的客户端上。该机制是Zookeeper实现分布式协调服务的重要特性。
Zookeeper采用ACL(Access Control Lists)策略来进行权限控制,类似UNIX文件系统的权限控制。Zookeeper定义了如下5种权限:
子节点的权限。
搜索微信公众号:java架构强者之路