zookeeper简介

1 zookeeper是什么

  zookeeper是一个分布式的、开源的、应用程序的、协调服务。 是一个分布式的、开源的、应用程序的、协调服务。

Google的三大论文(MapReduce、GFS、BigTable)在大数据领域意义深广,以此衍生出了Hadoop、HDFS、HBase。
而在这三篇论文里都提及Google的一个词——Chubby(lock service,面向松耦合的分布式锁服务),于是就有了 zookeeper。
zookeeper的两篇论文,一篇是Zab,介绍Zookeeper背后使用的一致性协议的(Zookeeper atomic broadcast protocol);还有 一篇是介绍zookeeper本身的。在这两篇论文中,都提到Zookeeper是一个分布式协调服务(a service for coordinating processes of distributed applications)。
什么是协调服务? 场景1 多线程中的一致性问题(例如,共享资源) 解决方案:进程内协调(java中叫同步)保证可用,使用简单的同步锁;挺好性能,使用读写锁
场景2 分布式系统的一致性问题(例如,远程调用服务的响应问题,网络问题) 解决方案:分布式协调服务,zookeeper

2 zookeeper提供什么 

2.1 文件系统 

文件系统 Zookeeper 的命名空间就是 Zookeeper 应用的文件系统,它和 linux 的文件系统很像,也是树状,这样就可以确定每个 路径都是唯一的,对于命名空间的操作必须都是绝对路径操作。与linux文件系统不同的是,linux文件系统有目录和文件的 区别,而Zookeeper统一叫做znode,一个 znode 节点可以包含子 znode,同时也可以包含数据。 所以总结说来,znode 即是文件夹又是文件的概念,所以在 zookeeper 这里面就不叫文件文件也不叫文件夹,叫 znode,每个znode有唯一的路径标识,既能存储数据,也能创建子znode。但是 znode 只适合存储非常小量的数据,不能超 过 1M,最好小于 1K。

2.2 Znode的介绍(非常重要)

     1、Znode 有两种类型:

短暂(ephemeral)(断开连接自己删除) 持久(persistent)(断开连接不删除) 

    2、Znode 有四种形式的目录节点(默认是 persistent )

    3、创建 znode 时设置顺序标识,znode 名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护 4、在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序 5、EPHEMERAL 类型的节点不能有子节点 6、客户端可以在 znode 上设置监听器 2.3 监听机制 监听机制 客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper 会通知客户端。监听机制保证 zookeeper 保存的任何的数据的任何改变都能快速的响应到监听了该节点的应用程序监听器 的工作机制,其实是在客户端会专门创建一个监听线程,在本机的一个端口上等待zk 集群发送过来事件。 注意:监听只生效一次 注意:监听只生效一次

3 zookeeper的应用场景 

3.1 配置管理 

配置管理(Configuration Management) 在分布式系统中,常会遇到这样的场景: 某个Job的很多个实例在运行,它们在运行时大多数配置项是相同的,如果想 要统一改某个配置,一个个实例去改,是比较低效,也是比较容易出错的方式。通过ZooKeeper可以很好的解决这样的问 题,下面的基本的步骤: 将公共的配置内容放到ZooKeeper中某个ZNode上,比如/service/common-conf 所有的实例在启动时都会传入ZooKeeper集群的入口地址,并且在运行过程中Watch /service/common-conf这个ZNode 如果集群管理员修改了了common-conf,所有的实例都会被通知到,根据收到的通知更新自己的配置,并继续Watch /service/common-conf

3.2 名字服务 

名字服务(NameService) 比如为了通过网络访问一个系统,我们得知道对方的IP地址,但是IP地址对人非常不友好,这个时候我们就需要使用 域名来访问。但是计算机是不能是别域名的。怎么办呢?如果我们每台机器里都备有一份域名到IP地址的映射,这个倒 是能解决一部分问题,但是如果域名对应的IP发生变化了又该怎么办呢?于是我们有了DNS这个东西。我们只需要访问 一个大家熟知的(known)的点,它就会告诉你这个域名对应的IP是什么。在我们的应用中也会存在很多这类问题,特别是 在我们的服务特别多的时候,如果我们在本地保存服务的地址的时候将非常不方便,但是如果我们只需要访问一个大家都熟知的访问点,这里提供统一的入口,那么维护起来将方便得多了。 下面以在HDFS中实现NameService为例,来说明实现NameService的基本布骤: 目标:通过简单的名字来访问指定的HDFS机群 定义命名规则:这里要做到简洁易记忆。下面是一种可选的方案: [serviceScheme://][zkCluster]-[clusterName],比如 hdfs://lgprc-example/表示基于lgprc ZooKeeper集群的用来做example的HDFS集群 配置DNS映射: 将zkCluster的标识lgprc通过DNS解析到对应的ZooKeeper集群的地址 创建ZNode: 在对应的ZooKeeper上创建/NameService/hdfs/lgprc-example结点,将HDFS的配置文件存储于该结点下 用户程序要访问hdfs://lgprc-example/的HDFS集群,首先通过DNS找到lgprc的ZooKeeper机群的地址,然后在ZooKeeper 的/NameService/hdfs/lgprc-example结点中读取到HDFS的配置,进而根据得到的配置,得到HDFS的实际访问入口 

3.3 组员管理 

组员管理(Group Membership) 在典型的Master-Slave结构的分布式系统中,Master需要作为“总管”来管理所有的Slave, 当有Slave加入,或者有Slave宕 机,Master都需要感知到这个事情,然后作出对应的调整,以便不影响整个集群对外提供服务。以Hbase为例,HMaster管 理了所有的RegionServer,当有新的RegionServer加入的时候,HMaster需要分配一些Region到该RegionServer上去,让其提供 服务;当有RegionServer宕机时,HMaster需要将该RegionServer之前服务的Region都重新分配到当前正在提供服务的其它 RegionServer上,以便不影响客户端的正常访问。下面是这种场景下使用ZooKeeper的基本步骤: Master在ZooKeeper上创建/service/slaves结点,并设置对该结点的Watcher 每个Slave在启动成功后,创建唯一标识自己的临时性(Ephemeral)结点/service/slaves/${slave_id},并将自己地址(ip/port)等 相关信息写入该结点 Master收到有新子结点加入的通知后,做相应的处理 如果有Slave宕机,由于它所对应的结点是临时性结点,在它的Session超时后,ZooKeeper会自动删除该结点 Master收到有子结点消失的通知,做相应的处理 

3.4 简单互斥锁 

简单互斥锁(Simple Lock) 在传统的应用程序中,线程、进程的同步,都可以通过操作系统提供的机制来完成。但是在分布式系统中,多个进程 之间的同步,操作系统层面就无能为力了。这时候就需要像ZooKeeper这样的分布式的协调(Coordination)服务来协助完成 同步,下面是用ZooKeeper实现简单的互斥锁的步骤,这个可以和线程间同步的mutex做类比来理解: 多个进程尝试去在指定的目录下去创建一个临时性(Ephemeral)结点 /locks/my_lock ZooKeeper能保证,只会有一个进程成功创建该结点,创建结点成功的进程就是抢到锁的进程,假设该进程为A 其它进程都对/locks/my_lock进行Watch

当A进程不再需要锁,可以显式删除/locks/my_lock释放锁;或者是A进程宕机后Session超时,ZooKeeper系统自动删 除/locks/my_lock结点释放锁。此时,其它进程就会收到ZooKeeper的通知,并尝试去创建/locks/my_lock抢锁,如此循环反

3.5 互斥锁 

互斥锁(Simple Lock without Herd Effect) 上一节的例子中有一个问题,每次抢锁都会有大量的进程去竞争,会造成羊群效应(Herd Effect),为了解决这个问题, 我们可以通过下面的步骤来改进上述过程: 每个进程都在ZooKeeper上创建一个临时的顺序结点(Ephemeral Sequential) /locks/lock_${seq} ${seq}最小的为当前的持锁者(${seq}是ZooKeeper生成的Sequenctial Number) 其它进程都对只watch比它次小的进程对应的结点,比如2 watch 1, 3 watch 2, 以此类推 当前持锁者释放锁后,比它次大的进程就会收到ZooKeeper的通知,它成为新的持锁者,如此循环反复 这里需要补充一点,通常在分布式系统中用ZooKeeper来做Leader Election(选主)就是通过上面的机制来实现的,这里的 持锁者就是当前的“主”。 

3.6 读写锁 

读写锁(Read/Write Lock) 我们知道,读写锁跟互斥锁相比不同的地方是,它分成了读和写两种模式,多个读可以并发执行,但写和读、写都互 斥,不能同时执行行。利用ZooKeeper,在上面的基础上,稍做修改也可以实现传统的读写锁的语义,下面是基本的步骤: 每个进程都在ZooKeeper上创建一个临时的顺序结点(Ephemeral Sequential) /locks/lock_${seq} ${seq}最小的一个或多个结点为当前的持锁者,多个是因为多个读可以并发 需要写锁的进程,Watch比它次小的进程对应的结点 需要读锁的进程,Watch比它小的最后一个写进程对应的结点 当前结点释放锁后,所有Watch该结点的进程都会被通知到,他们成为新的持锁者,如此循环反复 

3.7 屏障 

屏障(Barrier) 在分布式系统中,屏障是这样一种语义: 客户端需要等待多个进程完成各自的任务,然后才能继续往前进行下一步。 下用是用ZooKeeper来实现屏障的基本步骤: Client在ZooKeeper上创建屏障结点/barrier/my_barrier,并启动执行各个任务的进程 Client通过exist()来Watch /barrier/my_barrier结点 每个任务进程在完成任务后,去检查是否达到指定的条件,如果没达到就啥也不做,如果达到了就 把/barrier/my_barrier结点删除 Client收到/barrier/my_barrier被删除的通知,屏障消失,继续下一步任务 

3.8 双屏障

 双屏障(Double Barrier) 双屏障是这样一种语义: 它可以用来同步一个任务的开始和结束,当有足够多的进程进入屏障后,才开始执行任务; 当所有的进程都执行完各自的任务后,屏障才撤销。下面是用ZooKeeper来实现双屏障的基本步骤: 进入屏障: Client Watch /barrier/ready结点, 通过判断该结点是否存在来决定是否启动任务 每个任务进程进入屏障时创建一个临时结点/barrier/process/${process_id},然后检查进入屏障的结点数是否达到指定的 值,如果达到了指定的值,就创建一个/barrier/ready结点,否则继续等待 Client收到/barrier/ready创建的通知,就启动任务执行过程 离开屏障: Client Watch /barrier/process,如果其没有子结点,就可以认为任务执行结束,可以离开屏障 每个任务进程执行任务结束后,都需要删除自己对应的结点/barrier/process/${process_id} 

4 zookeeper的特点

     1)最终一致性: )最终一致性:client 不论连接到哪个 Server,展示给它都是同一个视图,这是zookeeper最重要的性能。     

    2)可靠性: )可靠性:具有简单、健壮、良好的性能,如果消息 m 被到一台服务器接受,那么它将被所有的服务器接受。 

    3)实时性: )实时性:Zookeeper 保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息。但由于网 络延时等原因,Zookeeper 不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用 sync()接口。 

    4)等待无关( )等待无关(wait-free) ) ): ):慢的或者失效的 client 不得干预快速的 client 的请求,使得每个client 都能有效的等待。

     5)原子性: )原子性:更新只能成功或者失败,没有中间状态。

    6)顺序性: )顺序性:包括全局有序和偏序两种:全局有序是指如果在一台服务器上消息 a 在消息 b前发布,则在所有 Server 上消 息 a 都将在消息 b 前被发布;偏序是指如果一个消息 b 在消息 a 后被同一个发送者发布,a 必将排在 b 前面
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值