ZooKeeper系列(一)ZooKeeper概览

374 阅读5分钟

概述

ZooKeeper是一个分布式的,开源的分布式应用程序的【协调服务】。它提供一系列简单的原语,分布式应用程序可以在这些原语的基础上实现更高级别的服务,用于同步、配置维护、组和命名。
它被设计为易于编程,并使用了一个数据模型,其风格与文件系统的目录树结构相似。它在Java中运行,并具有Java和C的绑定。
协调服务一直都是比较难的,特别容易出现竞争条件和死锁等错误。ZooKeeper背后的动机是减轻分布式应用程序从零开始实现协调服务的工作。

设计目标

  1. 简单的
    ZooKeeper允许分布式进程通过共享的分层的命名空间相互协调,该命名空间的组织类似于标准文件系统。命名空间由znode构成,类似于文件和目录。
    与典型的为存储而设计的文件系统不同的是,ZooKeeper数据保存在内存中,这意味着ZooKeeper可以实现高吞吐量和低延迟。 ZooKeeper实现非常重视高性能、高可用性和严格有序的访问。ZooKeeper的性能方面意味着它可以在大型分布式系统中使用;可靠性方面使其不会成为单点故障;严格的排序意味着复杂的同步原语可以在客户端实现。
  2. 可复制的
    与它所协调的分布式进程一样,ZooKeeper本身也打算在一组称为集群的主机上进行复制。
    组成ZooKeeper服务的服务器必须相互了解。它们在内存中维护一个状态映像,以及持久存储中的事务日志和快照。只要大多数服务器可用,ZooKeeper服务就会可用。 客户端连接到单个ZooKeeper服务器。客户端维护一个TCP连接,通过它发送请求、获取响应、获取监视事件和发送心跳。如果到服务器的TCP连接中断,客户机将连接到另一台服务器。
  3. 有序的
    ZooKeeper在每个更新的数字(反映ZooKeeper事务的顺序)上盖章,后续操作可以使用该顺序实现更高级别的抽象,例如同步原语。
  4. 快速的
    在“以读取为主”的工作负载中,它的速度尤其快。ZooKeeper应用程序运行在数千台机器上,当读操作比写操作更常见时,它的性能最好,比率约为10:1。

数据模型

与标准文件系统不同,ZooKeeper命名空间中的每个节点都可以拥有与其关联的数据和子节点。这就像有一个文件系统,它允许是一个文件也可以是一个目录。ZooKeeper用于存储协调数据:状态信息、配置、位置信息等,因此每个节点上存储的数据通常很小,字节到kb的范围内,我们使用znode来表示ZooKeeper数据节点。
znode维护一个stat结构,其中包括数据更改、ACL更改和时间戳的版本号,以允许缓存验证和协调更新。每当znode的数据发生更改时,版本号就会增加。例如,每当客户端检索数据时,它也会接收数据的版本。 存储在命名空间中的每个znode中的数据是自动读写的。读操作获取与znode关联的所有数据字节,而写操作替换所有数据。每个节点都有一个访问控制列表(ACL),用于限制谁可以做什么。 ZooKeeper也有临时节点的概念。只要创建znode的会话处于活动状态,这些znode就会一直存在。当会话结束时,将删除znode。

条件更新和监视

ZooKeeper支持监视的概念。客户端可以在znode上设置监视。当znode发生变化时,将触发并删除一个监视。当一个监视被触发时,客户端会收到一个数据包,告知znode已经改变了。如果客户端和ZooKeeper服务器之间的连接中断,客户端将收到本地通知。

ZooKeeper 3.6.0新特性:客户端还可以在znode上设置永久的递归监视,这些监视在触发时不会被删除,并且会触发对已注册znode和任何子znode的递归更改。

保证

  1. 顺序一致性——来自客户端的更新将按照它们被发送的顺序应用。
  2. 原子性——更新成功或失败,没有部分结果。
  3. 单个系统映像——客户端将看到相同的服务视图,无论它连接到哪个服务器。即客户端永远不会看到系统的旧视图,即使客户端故障转移到具有相同会话的不同服务器。
  4. 可靠性——一旦应用了更新,它就会一直保持,直到客户端覆盖了更新。
  5. 及时性——客户对系统的视图是保证在一定的时间范围内是最新的。

简单API

ZooKeeper的设计目标之一是提供一个非常简单的编程接口。因此,它只支持这些业务:
create:在树的某个位置创建节点
delete:删除一个节点
exists:测试某个位置上是否存在节点
get data:从节点读取数据
set data:将数据写入节点
get children:检索节点的子节点列表
sync:等待数据传播

实现

Replicated database是一个包含整个数据树的内存数据库。更新操作被记录到磁盘以获得可恢复性,写入操作在运用到内存数据库之前被序列化到磁盘。
每个ZooKeeper服务器都为客户端提供服务。客户端仅连接到一个服务器来提交请求。读请求从每个服务器数据库的本地副本获得服务。变更服务状态的请求(请求)由协议处理器来处理。
作为协议协议的一部分,所有来自客户端的写请求都被转发到一个名为Leader的服务器上。ZooKeeper服务器的其余部分(Follower)接收来自Leader的消息,并就消息传递达成一致。消息传递层负责在失败时替换Leader服务器,并将Follower服务器与Leader服务器同步。