翻译- O'Reilly ZooKeeper-第一章 入门

注:前一阶段的工作内容是设计和开发Distributed Query Coordinator分布式查询调度器,其中使用到了ZooKeeper。实际开发过程中发现之前对ZooKeeper的理解存在不少误区。翻阅O'Reilly的这本ZooKeeper后,在掌握正确的ZooKeeper编程技巧和理解内部原理方面都收获不小。简单翻译下,每天来一章吧,水平很有限,同行们随便看看就行。

第一部分 ZooKeeper概念和基础

         本部分内容介绍了ZooKeeper解决的问题以及在设计中做的妥协,对ZooKeeper感兴趣的读者都应该阅读。

第一章 入门

         过去,应用程序都运行在单机单CPU上。如今,一切已改变,在大数据和云计算的世界里,分布式应用运行在一组不断变化演进的机器上。

         协同这些程序的动作远比编写在单机上运行的程序要困难。开发者往往深陷协同逻辑的泥潭而减少了确保应用本身逻辑正确的时间——或者相反,在协同逻辑上花很少的时间,简单使用不够健壮的应急方案,这又容易导致单点故障。

         ZooKeeper的设计目的是提供健壮的服务,让应用开发者能够集中精力在应用逻辑而不是协同上。它对外提供了一套类似文件系统的API,让开发者实现常用的协同任务:比如Leader选举、组成员关系管理和元数据管理。ZooKeeper提供了两套主要API库实现—Java版和C语言版。服务组件则用Java实现,运行在一组特定的服务器上,具备容错能力和吞吐量可扩展性。

         当设计基于ZooKeeper的应用时,需要将应用程序数据和控制/协同数据进行区分。比如,邮箱用户只对他们的邮箱内容感兴趣,并不关心哪台服务器处理他们的邮件请求。邮箱内容是应用程序数据,而邮箱和邮件服务器的映射关系是协同数据(或者元数据)。ZooKeeper应该只管理后者。

ZooKeeper 使命

         解释ZooKeeper能做什么有点类似解释螺丝刀能做什么。最基本来讲,螺丝刀能够松紧螺丝,但这种解释没有真正讲清楚工具的能力。我们使用螺丝刀能够组装家具和电器,有时候还能在墙上悬挂画,而且螺丝刀的用途还远不止此。

         解释ZooKeeper的作用与此类似:它能够实现分布式系统协同任务。协同任务指包含多进程的任务。协同任务能够用于协作或者控制竞争。协作表示进程需要进程互相合作。比如在典型的Master-Worker架构中,Worker通知Master其空闲,然后Master分配任务给Worker。竞争则表示多个进程不能并行,必须互相等待。拿Master-Worker举例,只需要单独一个Master,但多个进程可能试图竞争成为Master。那么这多个进程之间必须实现排它锁。实际上,我们可以把任务竞争控制权看成是获取锁:获得控制锁的进程成为Master。

         如果你有多线程编程的经验,你会意识到这里有很多相似性:不管多个进程运行在同一台机器上还是在多台机器上,都有一些共同点,比如多线程环境下的同步原语在分布式系统中同样有用。但最重要的区别是,在典型的无共享架构中,不同的机器除了网络外没有其他东西共享。虽然可以用一些基于消息传递的算法来实现同步原语,但是基于具备某种特定有序性的共享存储来实现同步要简单得多,这正是ZooKeeper提供的解决方案。

         协同并不总是表现为Leader选举和锁等同步原语。配置性元数据也经常被进程用来给其他进程传达操作指示。比如在Master-Worker系统中,Workers需要知道他们被分配的任务,这些信息即使在Master崩溃的情况下也必须是可用的。

         让我们通过一些实际应用来进一步理解ZooKeeper的适用场景:

ApachaHBase

         HBase是基于Hadoop的数据存储系统。HBase使用ZooKeeper选举集群Master,跟踪可用的服务器,保存集群元数据。

Apache Kafka

         Kafka是一个消息发布订阅系统。Kafka使用ZooKeeper检测节点崩溃,主题发现,维护主题的生产和消费状态。

Apache Solr

         Solr是企业级搜索平台。在它的分布式模式下,SolrCloud使用ZooKeeper存储集群元数据,管理对元数据更新操作。

Yahoo! Fetching Service

         作为网络爬虫系统的一部分,Fetching Service通过缓存部分内容,在确保不违反Web服务器的政策,比如robots.txt的前提下,提高抓取效率。服务使用ZooKeeper来管理Master选举,崩溃检测和元数据存储。

Facebook Messages

         FacebookMessage是email、SMS、FacebookChat和Facebook Inbox的通信渠道整合应用。它使用ZooKeeper实现分片、failover和服务查找。

从更抽象的级别讨论,当使用ZooKeeper时,开发者将应用程序设计为ZooKeeper的客户端,通过ZooKeeper客户端API调用相关操作。通过ZooKeeper API能够实现:

  • 强一致性,有序性和持久化保障
  • 实现典型的同步原语
  • 更简单的处理并发方式。在现实的分布式系统中,并发往往导致错误结果

当然,ZooKeeper并非魔法,它不能开箱即用解决所有问题,所以理解ZooKeeper并掌握其技巧至关重要,这也正是本书的重要目标。我们还讨论了一些议题,是在使用ZooKeeper开发应用过程中遇到的实际问题,用来帮助刚刚接触ZooKeeper的开发者。

ZooKeeper名称缘由(略):Yahoo!had starteda variety of projects with the names of animals

在没有ZooKeeper的世界里幸存

         ZooKeeper并没有重新创造一类全新的应用程序。ZooKeeper只不过简化了分布式应用的开发过程,让开发过程变得更加敏捷,让实现变得更加健壮。

         之前的系统通过分布式锁等组件或者使用分布式数据库来实现协同。ZooKeeper也从这些系统中借用了不少概念,但它并不对外暴露锁接口或者通用的数据存储接口。ZooKeeper的设计理念是只专注于协同任务。它并不直接给开发者提供一系列同步原语,而是让开发者在其上灵活实现各种任务。

         不使用ZooKeeper也能构建分布式系统,但难度要大得多。ZooKeeper让开发者更关注应用逻辑而不是面对各种晦涩难懂的分布式系统概念。

ZooKeeper不适合场景

         ZooKeeper服务器集群适合管理应用中的协同数据,不适合大容量存储。数据库或者分布式文件系统更加适合大容量存储。

         ZooKeeper实现了一系列核心操作用来帮助在分布式系统中实现相关任务,但它并不直接帮你实现任务本身。比如它不是开箱即用地实现Master选举和活动进程跟踪。开发者通过ZooKeeper提供的工具来来决定如何实现这些协同任务。

The Apache Project

         ZooKeeper是Apache Software Foundation之下的开源项目。PMC(Project Management Committee)负责管理和监督项目。只有Committers可以check in patches,但任何开发者都可以贡献patches。活跃的贡献者可以成为Committers。对项目的贡献也不仅限于代码patches——也可以是其他形式,和社区里其他成员互动的结果。在邮件列表中有很多关于新特性的讨论和新手的问题等。我们强烈建议对加入社区感兴趣的开发者订阅邮件列表,加入讨论。

使用ZooKeeper构建分布式系统

         在本书中,我们将分布式系统定义为由多个立并发运行在多台物理机器上的组件组成的系统。将系统设计为分布式有很多理由。分布式系统通过复制并行各个组件能够充分利用多处理器资源。分布式系统也可能是地理上分布的,应用服务器分散在不同的位置。

        du立的协同组件有不少优点。首先,组件能被du立设计和实现。能够被多个应用共享。其次,让系统架构在协同方面更加简洁。最后,du立运行和管理协同组件,可以简化生产环境中解决问题的过程。

         现在软件往往都是多线程的,能够充分利用现代多核心处理器的能力。ZooKeeper服务器和客户端进程也是如此。

         分布式系统中的进程通常有两种方式进行通信:通过网络交换消息或者使用共享存储。ZooKeeper使用共享存储模型来实现协同和同步原语。但是共享存储本身也需要网络通信。网络通信值得强调,它往往导致分布式系统设计变得复杂化。

在真实系统中,需要特别关注以下问题:

消息延迟

         消息会出现随机性延迟,比如因为网络阻塞。这种任意的延迟会产生无法预料的结果。比如进程P可能在进程Q之前发送消息,但是Q的消息可能先于P被传递。

处理器速度

         操作系统调度和超负荷都可能会引起消息处理的延迟。当一个进程发送消息给其他进程,整个消息延迟由发送者的处理时间,传输时间和接受者的处理时间组成。如果发送者和接受者都需要调度时间去处理,那么消息延迟会变高。

时钟漂移

         系统使用不同的时间概念判断事件发生时间。处理器时钟是不可靠的,因为它可能会发生任意漂移。依赖处理器时钟容易导致错误结果。

         以上问题让判断一个进程是已经崩溃还是只是发生延迟非常困难。没有接受到进程的消息,可能意味着它已经崩溃,也可能意味着发生了网络延迟,处理延迟和时钟漂移等异常。不能区分这些情况的系统都被称为异步的。

         ZooKeeper恰恰被设计成能够简化处理这些问题。虽然ZooKeeper不能让问题消失或者使其对应用完全透明,但至少能让问题变得易于处理。


示例:Master-Worker应用

         我们已经从理论上讨论了分布式系统,现在开始付诸实践。考虑一种已经被广泛应用的分布式系统设计架构:Master-Worker架构。HBase(Google Bigtable的开源实现)就是其中一个重要例子,。总体来讲,HMaster负责管理所有可用的HReginServer,分配regions给它们。在此并不准备展开讨论HBase,我们鼓励读者查阅HBase相关文档了解其使用ZooKeeer的更多细节。现在关注的是通用Master-Worker架构。

Figure 1-1. Master-worker example

         通常来讲,在这样的架构中Master负责跟踪可用的Workers和任务,将任务分配给Workers。使用ZooKeeper实现这种架构是非常典型的,它能够阐明很多典型任务,比如Master选举,跟踪Workers和元数据管理。

         实现Master-Worker系统,必须解决三类关键性问题:

Master崩溃

         如果Master出错不可用,系统不能分配新的任务或者重新分配已经失败的任务

Worker崩溃

         如果worker崩溃,已经分配给它的任务不能完成

通信失败

         如果Master和Worker不能通信,Worker不能获得新分配的任务         

         为了解决这些问题,系统必须在Master崩溃时,选举出新的Master,必须能够判断哪些Worker是可用的,必须能够判断某些Worker的状态相比其他Worker是否已经过时。在下面几节中,我们分别简短讨论每个问题。

Master崩溃

         应对Master崩溃,必须依靠备用Master,当Master崩溃时,备用Master进行接管。失效转移(failover)不只是开始处理新的用户请求,新的Master必须恢复之前Master崩溃时系统的状态。而且恢复操作不能依赖已经崩溃的Master,必须从其他地方进行:正好从ZooKeeper进行恢复。

         恢复状态不是唯一的重要问题。假设之前的Master又上线了,而备用Master认为它已经崩溃,这种情况时有发生,比如之前的Master系统超负荷,消息产生了延迟等。这时候备用Master已经接管了所有操作,成为第二个Master。更糟糕的是,如果一些Worker由于网络分割故障不能连接上先前的Master,开始追随第二个Master。这种场景通常被称之为“脑分裂”,会导致系统不一致。当处理Master崩溃时,避免“脑分裂”现象是至关重要的。

Worker崩溃

         客户端提交任务给Master,master将任务分配给可用的Workers,Workers接受分配的任务并向Master汇报任务的执行状态,然后Master通知客户端任务的执行结果。

         如果Worker崩溃,未完成的任务需要被重新分配。首先,Master必须能够检测到Worker发生崩溃,能够让其他可用Worker来执行任务。在Worker崩溃的场景下,任务可能没有被完全执行,或者完全执行后还没来得及汇报结果。如果任务执行具有副作用,那么恢复过程必须进行状态清理。

通信失败

         如果Worker和Master连接中断,重新分配任务可能会导致任务被重复执行。如果任务被多次运行是可接受的,重新分配任务时可以不用检查任务是否已经被执行,否则,应用必须处理多个Worker试图运行同一个任务的情况。

         通信失败中的另外一个问题是锁带来的影响。因为节点可能崩溃,系统容易发生网络分割故障。如果发生这些情况,锁依然还会阻止其他进程。ZooKeeper通过以下机制处理这个问题。首先,客户端能够创建临时节点。其次,客户端定期向ZooKeeper集群发送通知。如果客户端没有及时通知服务端,客户端创建的所有临时节点将会被删除。

         前面曾经提到,在存在消息延迟的系统中,很难区分出客户端是已经崩溃还是只是运行迟缓,所以,当我们怀疑客户端已经崩溃时,我们实际上需要假设它可能只是运行迟缓,可能将来还会执行其他操作。

任务摘要

         总结之前的描述,我们归纳出以下Master-Worker架构上的需求:

Master选举

         Master可用非常关键,才能够分配任务给Workers。

失败检测

         Master能够检测到Workers崩溃或者连接中断。

组成员管理

         Master能判断哪些机器可以执行任务

元数据管理

         Master和Workers能够以可靠的方式存储任务分配情况和运行状态。

         最理想的情况当然是这些任务都以原语的方式直接暴露给应用,所有的实现细节都对开发者透明。ZooKeeper提供关键机制用来实现相应原语,开发者选择最符合自己需求的方式实现,从而集中精力关注在应用逻辑上。

为什么分布式协同很难

         略。。。又强调一遍,本来就很难

ZooKeeper Is a Success,with Caveats

         略。。。广告嫌疑



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值