Zookeeper: 一个分布式应用的分布式协调服务
zookeeper 是一个分布式的,开源的协调服务框架,服务于分布式应用程序。
它暴露了一系列的基础的操作服务,因此分布式应用能够基于这些服务,构建出更高级别的服务,比如同步,配置管理,分组和命名服务。
zookeeper设计上易于编码,数据模型构建在我们熟悉的树形结构目录风格的文件系统中。
zookeeper运行在java中,同时支持java和C 语言。正确的实现协调服务是公认的难干的差事。 他们及其容易出错,比如资源竞争和死锁.
zookeeper 的使命和力量来源于,将分布式应用从处理协调服务的泥潭中走出来。
zookeeper的设计目标
zookeeper是非常简单的. zookeeper允许 分布式进行通过一个共享的树形命名空间进行互相协调,这一命名空间跟文件系统的组织方式类似.
zookeeper命名空间由数据寄存器组成,zookeeper中,我们称他为,znodes, 这跟文件和目录非常类似..
不像一个典型的文件系统,其设计时就是为了存储数据.而zookeeper 数据是保存在内存中的,这也就意味着zookeeper能实现一个高吞吐量和低延迟.(因为内存操作效率高)
zookeeper实现 对高性能,高可用性,严格的顺序访问分外关注,. Zookeeper性能比较优异也就意味着它可以使用在大的分布式系统中.
可靠性方面让我们远离了单点故障. 严格的顺序访问意味着复杂的同步原语可以在客户端实现.
zookeeper是有副本的, 就像分布式的处理协调服务一样,zookeeper 本身就打算在服务器集群中使用副本机制,我们称之为全体.
组成zookeeper 服务的所有机器节点互相之间都必须感知到对方. 他们维护着当前机器状态的内存快照,有事务日志和持久化存储的快照.
只要大多数的机器是可用的那么整个zookeeper服务就是可用的.
客户端连接到其中一台zookeeper服务器,客户端和zookeeper服务器保持一个tcp连接,通过tcp连接发送请求获得响应,
获取事件监听,发送心跳等等. 如果TCP连接被中断了,客户端会连接到另外一台zookeeper服务器.
zookeeper是有序的, zookeeper给每一次更新操作都赋予一个编号,他这个编号反应了对zookeeper的事务性修改顺序.
随后的操作能够使用这一顺序去实现更高级别的抽象,比如同步原语.
zookeeper是非常快的,尤其是针对 读占据主要地位的应用负载的应用. zookeeper应用 运行在成千上万的机器中,
当读写比例为10:1 情况下,zookeeper的性能是最优的.
数据模型和命名空间的体系结构
zookeeper提供的命名空间非常想我们标准的文件系统. 命名就是一系列用/分割的路径元素. 每一个zookeeper节点的命名空间都是用路径
进行标识的.
节点和临时节点
不像标准的文件系统,zookeeper 命名空间中的每个节点能够有数据关联,也有子节点.
就好比是文件系统中一个文件对象即可以是一个文件也可以是一个文件夹.(zookeeper被设计用来存储协调数据:
状态信息,配置信息,位置信息等等, 因此数据存储在每个节点中通常非常小,从几个字节到几千字节之间),
我们使用znode这个术语来使得我们讨论zookeeper数据节点相关内容时语义更加清晰明确.
znode管理着包含这一个状态结构数据,它包含数据修改的版本号,ACL修改及时间戳, 允许缓存校验和协调更新.
znode数据每修改一次,版本号加一. 举个实际的例子,每次客户端收到数据的同时,也收到当前数据的版本号.
每一个节点都有一个ACL访问控制列表,严格控制着谁能进行操作.
zookeeper 也有会话级别的节点的语义支持,这些znode节点随着会话的创建而激活,会话的结束的时候节点被删除.
会话级别的节点在实现实现例子的时候非常有用.
条件更新和监听
zookeeper支持监听, 客户端能够设置监听znode节点. 当znode节点变更时可能触发或者移除监听.当监听事件被触发了,
客户端将会收到数据通知包,告诉客户端节点数据被修改了. 同时如果当前客户端和zookeeper节点的连接被断开了.
客户端将收到一个本地通知. 这些特性都能用在 具体例子中
zookeeper的保证
zookeeper 简单而性能优异. 由于他简单快速的目标,他成为构建许多更加复杂服务的基础,比如同步服务,他提供了一系列的保证.
1 顺序一致性: 来自客户端的更新操作将会按照顺序被作用.
2 原子性操作: 更新要么全部成功,要么全部失败,没有部分的结果.
3 统一的系统镜像 无论客户端链接的是哪台服务器,都能获得同样的服务视图,也就是说他是无状态的.
4 可靠性保证 一旦写入操作被执行(作用到服务器),这个状态将会被持久化,直到其他客户端的修改生效.
5 时间线特性 客户端访问服务器系统镜像能在一个特定时间访问内保证当前系统是实时更新的
简单的操作API
zookeeper的设计原则之一就是提供简单的编程接口. 因此,他仅仅提供了以下几个操作.
1 创建 在目录结构树的某个位置创建一个节点
2 删除 删除某个节点
3 判断是否存在 判断某个位置上是否存在指定节点
4 获取数据 从节点中获取数据
5 设置/写入数据 写入数据到某个节点中
6 同步 等待写入数据传播到其他节点
想要进一步深入的探讨这些特性和操作,以及他们是如何实现更高级别的操作,请参看使用示例的相关内容
zookeeper实现细节
zookeeper组件构成图中 展示了zookeeper服务中比较高级的组件服务.
除了请求处理器的异常情况之外. 组成zookeeper服务的每一台zookeeper服务器 保存着每个组件自身备份的副本.
副本数据库是一个内存数据库,保存着整个目录结构树的数据.
所有的更新操作都记录在磁盘日志当中,用于异常情况的恢复. 在更新作用到内存数据中之前,所有的写入操作都是串行的,
这就保证了数据的强一致性。
每个zookeeper服务器节点服务若干个客户端. 客户端连接到某一个指定的服务器节点(随机分配算法分配的吧)和zookeeper进行交互.
读请求都是由每个zookeeper服务器内存数据库的本地副本进行服务的(可以提高读的性能,
这也就是为什么zookeeper在读写比例为10:1的情况下,性能最佳的原因)
涉及到修改服务器状态和数据的写入操作,需要通过一致性协议进行处理.
一致性协议中规定: 所有的写入操作都是有选举出来的唯一机器即我们称之为leader(主节点) 的节点进行操作.
剩下的zookeeper机器,称之为从节点(跟随者),接收来自leader节点的建议 并同意传输过来的消息.
也就是说对消息只有服从和传输的特性. 消息层 关注的是当leader节点挂掉之后怎么去替换他,并同步leader节点和follower节点之间的数据.
zookeeper 使用客户端端原子消息协议.因为消息层是原子的,zookeeper 能保证本地副本和服务器版本相同步.
当leader节点接收到写入请求时, leader节点会计算下 当前系统的状态是什么,什么时候讲写入作用到服务器,
并把当前写入操作转换成一个事务并记录下新的状态.
使用情况
zookeeper的编程接口 设计的非常简单,但是用这些能实现一些其他更高级别的操作,比如同步原语,对成员进行分组和选举等等.
一些分布式的应用用这些接口实现一些其他比较高级的功能
性能
zookeeper 被设计的号称高性能框架,但是事实情况如何呢?
来自雅虎的zookeeper开发团队的研究证明了这点.
(可以查看下zookeeper 吞吐量随着读写比例变化的图表,即上图)
在读占主要比例的应用中,性能尤佳,因为写操作涉及到服务器之间状态的同步.尤其是在协调服务这个典型案例中表现的尤其突出.
zookeeper 吞吐量和读写比例的变化关系用的是zookeeper3.2版本,运行在 双核 2Ghz 及SATA 15k RPM 处理器配置的服务器中.
其中一个负责zookeeper 日志设备. 快照信息写入操作系统驱动中.
写入请求是1Kb写入, 读请求也是1kb的写入(读写单元都是1Kb).
servers 标示着 整个zookeeper的集群大小, 即组成zookeeper服务的服务器数.
整个zookeeper集群有个限定,客户端都不能直接连接zookeeper的leader 节点.
可靠性
为了展示下,我们系统随着时间的推移及错误出现,我们运行了一个一个由7个机器组成的zookeeper服务中,我们使用和此前一样饱和度的基准测试,
但是这次我们设定写入操作的比例为30%, 这个比例是对我们预期的负载的保守估计值.
这个图中有几个比较关键的观测点.首先,如果从节点失败并快速恢复了,即使从节点失败了,zookeeper仍然能够承受住一个比较高的吞吐量.
但是,更为重要的一点事,leader节点的选举算法 能让系统快速恢复,防止吞吐量在短时间内迅速降低.观察发现, zookeeper能在200毫秒内选举出新的leader节点,
第三,随着从节点的恢复,zookeeper的吞吐量能快速提升,一旦恢复的从节点开始处理请求.
zookeeper 项目
zookeeper 已经在许多企业级应用中获得成功,雅虎内部使用zookeeper 进行协调和失败恢复服务,及消息中间人服务
消息中间人是一个 高可扩展性的 基于发布-订阅的消息系统,
他管理成千上万个消息主题,可以实现副本和数据传输的功能.
zookeeper在雅虎内部还用于数据抓取服务,即网络爬虫,同时致力于失败恢复.
许多雅虎的广告系统使用zookeeper 实现高可靠服务.
我们欢迎并鼓励所有用户和开发者加入我们这个社区,发挥大家的专长。
详情请关注Apache中的zookeeper项目。