Zookeeper: 分布式过程协同技术详解

Zookeeper的使命

Zookeeper主要作用为在分布式系统中协调多个任务,一个任务可以是协作或者是竞争。协作意味着多个进程需要一同处理某些事情,一些进程采取某些行动使得其他进程可以继续工作,例如在主从模式中,主节点与从节点协作,主节点分配任务给从节点;竞争是指两个进程不能同时处理工作,一个进程必须等待另一个进程,同样在主从工作模式中,通过互斥排它锁的方式保证任何时刻只有一个主。

使用Zookeeper的应用包括如下几个大家非常熟悉的系统:

  • Apache HBase
  • Apache Kafka
  • Apache Solr

除了上述应用之外,还有很多使用Zookeeper的例子。我们在使用Zookeeper的时候,往往都是通过Zookeeper客户端暴露的API来使用的,Zookeeper的客户端API功能强大,其中包括:

  • 保障强一致性、有序性和持久性
  • 实现通用的同步原语的能力
  • 在实际分布式系统中,并发往往导致不正确的行为,Zookeeper提供了一种简单的并发处理机制

Zookeeper不适用的场景

Zookeeper应该用来管理分布式应用的协作关键数据,这些数据一般都是精且少的,Zookeeper不适合用作海量数据存储。在实际应用中,建议将协同数据和应用数据分开,协同数据可以使用Zookeeper,而应用数据则可以考虑数据库或者分布式文件系统等存储方案。

关于Apache项目

Zookeeper是一个托管到Apache软件基金会的开源项目,Apache的项目管理委员会负责项目管理和监督。只有技术专家可以检查补丁,但任何开发人员都可以贡献补丁。

通过Zookeeper构建分布式系统

我们采用分布式设计系统有很多原因,分布式系统能够利用多处理器的运算能力来运行组件,比如并行复制任务。一个系统也许需要分布在不同的地点,比如一个应用由多个不同地点的服务器提供服务。

在分布式系统中,我们需要特别注意以下问题:

  • 消息延迟:消息传输可能会发生任意延迟,比如因为网络拥堵。这种延迟可能会导致不可预期的后果,比如进程P先发送了一个消息,之后另一个进程Q发送了消息,但是也许进程Q的消息先完成传送。
  • 处理器性能:当一个进程向另一个进程发送消息时,整个消息的延迟时间约等于发送端消耗的时间、传输时间、接收端的处理时间的总和,因此操作系统的调度和超载也可能会导致消息处理的延迟。
  • 时钟偏移:使用时间概念的系统并不少见,比如确定某一时间系统中发生了哪些事件。但处理器时钟并不可靠,它们之间也会发生任意的偏移,依赖处理器时钟也许会导致错误的决策。

这些问题导致一个结果,那就是在实际情况中我们很难判断一个进程是崩溃了还是某些因素导致了延时。

Zookeeper的精确设计简化了这些问题的处理,它实现了重要的分布式计算问题的解决方案,为开发人员提供了某种程度的封装,减轻了我们的开发。

Zookeeper基础

分布式协作通常需要暴露一些原语,例如分布式锁机制需要提供创建(create)、获取(acquire)和释放(release)等原语。但作为分布式协调中间件来说,提供原语有两个缺点:1)分布式协作有很多种类,要么提供一份详尽的原语列表,要么时刻保持原语的更新;2)这种以原语提供服务的方式缺乏灵活性。

因此,Zookeeper另辟蹊径,它不直接暴露原语,而是通过提供类似于文件系统的方式允许应用实现自己的原语。Zookeeper主要维护一个树形的数据结构,结构中的节点被称为znode。下图描述了一个znode树的结构,根节点包含4个子节点,其中三个子节点拥有下一个节点,叶子节点存储了数据信息。

zookeeper-tree

API概述

znode节点可以含有数据,也可以没有。如果一个znode节点包含数据的话,那么数据是以字节数组的形式来存储。字节数组的具体格式依赖于应用本身的实现,Zookeeper不直接提供解析的支持,应用可以使用如Protocol Buffer、Thrift、Avro或MessagePack等序列化包来处理保存于znode节点的数据,但往往UTF-8或ASCII编码的字符串已经够用了。

Zookeeper的API提供了如下操作:

  • create /path data:创建一个名为/path的znode节点,并包含data数据
  • delete /path:删除名为/path的znode
  • exists /path:检查是否存在名为/path的节点
  • setData /path data:设置名为/path的znode的数据为data
  • getData /path:返回名为/path节点的数据
  • getChildren /path:返回/path节点的子节点列表

需要注意的是,Zookeeper并不允许局部的写入或读取,当进行数据读写时,znode的内容会被整个替换或读取出来。

znode的不同类型

当新建znode时,需要指定该节点的类型,不同的类型决定了znode节点的行为方式。

持久节点和临时节点

znode节点可以是持久(persistent)节点或者临时(ephemeral)节点。持久节点只能通过delete调用来进行删除,而临时节点在客户端崩溃或者关闭连接时也会被删除。

持久节点可以为应用保存数据,即使其创建者不再存活,数据也可以保存下来而不丢失。而临时节点传达了应用某些方面的信息,那就是仅当创建者的会话有效时这些信息必须有效保存。例如在主从模式的例子中,master创建的znode可以为临时节点,当该节点存在时意味着当前存在一个master并且它正常运行中;如果master对应的临时节点消失,那意味着主节点崩溃了,其他备份节点可以接替原master。

有序节点

一个znode还可以设置为有序(sequential)节点,一个有序的znode会被分配唯一的单调递增的整数。当创建有序节点时,一个序号会被追加到路径之后。例如创建一个有序znode节点,其路径为/tasks/task-,那么Zookeeper将会分配一个序号,如1,并将这个数字追加到路径之后,最后该节点为/tasks/task-1。

总之,znode一共有4种类型:

  • 持久的(persistent)
  • 临时的(ephemeral)
  • 持久且有序的(persistent_sequential)
  • 临时且有序的(ephemeral_sequential)

监视与通知

轮询通常代价比较大,考虑下面这个例子,第二次调用getChildren /tasks返回了相同的值,也就是一个空的集合,但这个调用其实是没必要的。

lunxun

因此Zookeeper提供了基于通知(notification)的机制:客户端向Zookeeper对某个znode设置监视点(watch),当该znode发生变更时会触发一个通知。但监视点是单次触发的,触发之后需要重新设置新的监视点。下图是使用监视点的示意图:

notification

客户端可以设置多种监视点:

  • 监听znode的数据变化
  • 监听znode子节点的变化
  • 监听znode的创建或删除

另外值得注意的是,Zookeeper并没有提供

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值