关于Zookeeper

来源:互联网 发布:手机cad机械制图软件 编辑:程序博客网 时间:2024/05/12 12:10
 

应用需求

大部分分布式应用需要一个主控、协调器或控制器来管理物理分布的子进程(如资源、任务分配等)

目前,大部分应用需要开发私有的协调程序,缺乏一个通用的机制

协调程序的反复编写浪费,且难以形成通用、伸缩性好的协调器

Zookeeper:提供通用的分布式锁服务,用以协调分布式应用(如,为HBase提供服务)。Zookeeper并不针对应用的special需求,而是向应用提供平台和API,由应用自己通过Zookeeper实现协调控制。

 

功能

Zookeeper is a distributed, open-source coordination service for distributed applications. It exposes a simple set of primitives that distributed applications can build upon to implement higher level services for synchronization, configuration maintenance, and groups and naming.

Zookeeper提供两方面的一致性,1)Linearizable writes: all requests that update the state of Zookeeper are serializable and respect precedence; 2)FIFO Client order: all requests from a given Client are executed in the order that they were sent by the Client.

另外,Zookeeper不同于以往的一些一致性协议:以前的多使用blocking(阻塞)的方式,因而性能较慢,而且慢Client会影响后面的快Client;Zookeeper采用wait-free的方式,提高响应性能。

 

基本架构

Zookeeper分为2个部分:服务器端和客户端。Client代表需要一致性服务的各节点,为这些物理节点安装Zookeeper客户端。服务器端可以运行在两种模式下,一种是单机模式,另外一种是集群模式。单机模式就是只有一个Zookeeper service ,这对于测试来讲非常方便,但不能保证服务的高性能和高可靠性;另一种就是集群模式,在这种模式下,只要集群中的大多数节点正常工作,就可以提供稳定的高性能服务。

集群模式下,Zookeeper Server为一个多副本的集群。集群中的每个Server都保存了一份数据副本,全局数据一致,分布式读写。首先在Server中选择一个Leader,其它Server称为Follower,当Leader失效或到期也会触发选举。Zookeeper Server集群会通过Paxos算法选出这个Leader,由Zab实现,具体的选举协议十分复杂这里就不说了。

每个Server都对Client提供服务,Client连接到具体的某一个Server以提交请求。读请求由每个Server的本地数据库响应,而所有的写请求需传递到Leader,由Leader通过广播更新Follower。

 

操作流程

任意一个Server收到write request时,会将其转发到Leader。Client通过Zookeeper的API提交的write request包含version,为了保证FIFO,Leader会通过 write request的version确定针对每一个Client发来的request的执行顺序。选好当前要执行的request后,Leader会采用类似Paxos的协议一致性地更新所有Server。具体来说,Leader向所有Server发起询问投票,当半数以上的Server同意后,Leader提交这个写操作并认为写成功返回。也就是说,此时半数以上Server已经更新,另外一小部分Server的更新还在路上,而Leader已经返回本次写操作,开始执行下一个操作。可以想象,每个时刻都有新的操作在Leader上执行,也有旧的操作正在更新Server,还有一些已经提交的操作还在赶赴Server的路上,这就像一个pipeline,从而提高了效率。每个Server都有一个in-disk存储和in-memory数据库,写操作到达后会先更新in-disk存储再更新in-memory数据库.

Server收到Client的read request后通过本地in-memory数据库响应,因而有较快的速度。但有一个问题,前面说到写操作只保证更新半数以上的Server,因而如果响应read的Server恰好属于尚未更新的那另外一部分,则read会得到旧的数据。于是,Zookeeper提供sync操作,若Client要求此次read必须读到最新数据,则在read前先发出sync,同步该Server与Leader的数据。

若某个Server出错退出,Client需连接到另一个Server,此时的问题是,这个新的Server与出错退出的Server上的更新进度可能不同。Zookeeper保证,出错退出的Server所完成过的更新操作,新的Server也都完成过。具体方法是每个Server都维持一个zxid,完成一次更新操作后,zxid++。Client会对比新旧Server的zxid以判断新Server执行过的更新是否多于退出的旧Server。

为了出错后recover,Server会定时snapshot。Zookeeper为了提高性能采用fuzzy snapshot,就是在snapshot时不阻塞更新的执行,因而在recover时,可能会有一些更新重复做了两遍,不过由于我们保证了更新的顺序,重复做也不会影响结果。

 

数据结构

Zookeeper is similarly to a standard file system. Zookeeper Server集群上存储着一个类似UNIX的文件系统,每个Client节点在文件系统上建立一个目录或文件(即znode)代表自己。Znode中存储着一系列结构化数据,表示该节点的元数据信息,如version numbers for data changes, ACL changes, and timestamps。对某个znode的更改都要改写其对应的文件,从而通过文件系统实现了锁。

 

提升Zookeeper集群的性能

我们说性能,可以从两个方面去考虑:写入的性能与读取的性能。

由于Zookeeper的写入首先需要通过Leader,然后这个写入的消息需要传播到半数以上的Follower通过才能完成整个写入。所以整个集群写入的性能无法通过增加服务器的数量达到目的,相反,整个集群中Follower数量越多,整个集群写入的性能越差。

Zookeeper集群中的每一台服务器都可以提供数据的读取服务,所以整个集群中服务器的数量越多,读取的性能就越好。但是Follower增加又会降低整个集群的写入性能。为了避免这个问题,可以将Zookeeper集群中部分服务器指定为Observer。Observer主要是为提升Zookeeper的性能,Observer和Follower的主要区别就是Observer不参与Leader agreement vote处理,只提供读节点的处理。
原创粉丝点击