zookeeper入门学习(一)

来源:互联网 发布:whoo在淘宝有旗舰店吗 编辑:程序博客网 时间:2024/05/21 03:17

使用dubbo的时候使用过zookeeper,但在面阿里的时候被问到还是有很多东西不清楚,因此决定系统的学习一下,计划如下
第一阶段:

|—理解ZooKeeper的应用

|---ZooKeeper是什么|---ZooKeeper能干什么|---ZooKeeper 怎么使用

第二阶段:

|—理解ZooKeeper原理准备

|---了解paxos|---理解 zab原理|---理解选举/同步流程

第三阶段:

|---深入ZooKeeper原理    |---分析源码    |---尝试开发分布式应用

Zookeeper是什么?

ZooKeeper是一种为分布式应用所设计的高可用、高性能且一致的开源协调服务,它提供了一项基本服务:分布式锁服务。它是一个针对大型分布式系统的可靠协调系统,主要是用来解决分布式应用中经常遇到的一些数据管理问题,可以高可靠的维护元数据。提供的功能包括:配置维护、名字服务、分布式同步、组服务等。ZooKeeper的设计目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。

Zookeeper怎么用?

Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储,但是 Zookeeper 并不是用来专门存储数据的,它的作用主要是用来维护和监控你存储的数据的状态变化。通过监控这些数据状态的变化,从而可以达到基于数据的集群管理,后面将 会详细介绍 Zookeeper 能够解决的一些典型问题。

注意一下这里的”数据”是有限制的:

(1) 从数据大小来看:我们知道ZooKeeper的数据存储在一个叫ReplicatedDataBase 的数据库中,该数据是一个内存数据库,既然是在内存当中,我就应该知道该数据量就应该不会太大,这一点上就与hadoop的HDFS有了很大的区别,HDFS的数据主要存储在磁盘上,因此数据存储主要是HDFS的事,而ZooKeeper主要是协调功能,并不是用来存储数据的。

(2) 从数据类型来看:正如前面所说的,ZooKeeper的数据在内存中,由于内存空间的限制,那么我们就不能在上面随心所欲的存储数据,所以ZooKeeper存储的数据都是我们所关心的数据而且数据量还不能太大,而且还会根据我们要以实现的功能来选择相应的数据。简单来说,干什么事存什么数据,ZooKeeper所实现的一切功能,都是由ZK节点的性质和该节点所关联的数据实现的,至于关联什么数据那就要看你干什么事了。

例如:

  ① 集群管理:利用临时节点特性,节点关联的是机器的主机名、IP地址等相关信息,集群单点故障也属于该范畴。

  ② 统一命名:主要利用节点的唯一性和目录节点树结构。

  ③ 配置管理:节点关联的是配置信息。

  ④ 分布式锁:节点关联的是要竞争的资源。

Zookeeper应用场景

zk结构通常如下图:
这里写图片描述
Zookeeper 这种数据结构有如下这些特点:

① 每个子目录项如novel都被称作为 znode,这个 znode 是被它所在的路径唯一标识,如 Server1 这个 znode 的标识为 /novel/Server1;

② znode 可以有子节点目录,并且每个 znode 可以存储数据,注意 EPHEMERAL(临时节点) 类型的目录节点不能有子节点目录;

③ znode 是有版本的,每个 znode 中存储的数据可以有多个版本,也就是一个访问路径中可以存储多份数据;

④ znode 可以是临时节点,一旦创建这个 znode 的客户端与服务器失去联系,这个 znode 也将自动删除,Zookeeper 的客户端和服务器通信采用长连接方式,每个客户端和服务器通过心跳来保持连接,这个连接状态称为 session,如果 znode 是临时节点,这个 session 失效,znode 也就删除了;

⑤ znode 的目录名可以自动编号,如 App1 已经存在,再创建的话,将会自动命名为 App2;

⑥ znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个是 Zookeeper 的核心特性,Zookeeper 的很多功能都是基于这个特性实现的。

应用场景

  • 数据发布与订阅

    例如:同一个应用系统需要多台 PC Server 运行,但是它们运行的应用系统的某些配置项是相同的,如果要修改这些相同的配置项,那么就必须同时修改每台运行这个应用系统的 PC Server,这样非常麻烦而且容易出错。将配置信息保存在 Zookeeper 的某个目录节点中,然后将所有需要修改的应用机器监控配置信息的状态,一旦配置信息发生变化,每台应用机器就会收到 Zookeeper 的通知,然后从 Zookeeper 获取新的配置信息应用到系统中。ZooKeeper配置管理服务如下图所示:
    这里写图片描述

    Zookeeper很容易实现这种集中式的配置管理,比如将所需要的配置信息放到/Configuration 节点上,集群中所有机器一启动就会通过Client对/Configuration这个节点进行监控【zk.exist(“/Configuration″,true)】,并且实现Watcher回调方法process(),那么在zookeeper上/Configuration节点下数据发生变化的时候,每个机器都会收到通知,Watcher回调方法将会被执行,那么应用再取下数据即可【zk.getData(“/Configuration″,false,null)】。

  • 统一命名服务

    在分布式系统中,通过使用命名服务,客户端应用能够根据指定的名字来获取资源服务的地址,提供者等信息。被命名的实体通常可以是集群中的机器,提供的服务地址,进程对象等等,这些我们都可以统称他们为名字(Name)。其中较为常见的就是一些分布式服务框架中的服务地址列表。通过调用ZK提供的创建节点的API,能够很容易创建一个全局唯一的path,这个path就可以作为一个名称。Name Service 已经是Zookeeper 内置的功能,你只要调用 Zookeeper 的 API 就能实现。如调用 create 接口就可以很容易创建一个目录节点。

    应用举例:阿里开源的分布式服务框架Dubbo中使用ZooKeeper来作为其命名服务,维护全局的服务地址列表。在Dubbo实现中: 服务提供者在启动的时候,向ZK上的指定节点/dubbo/${serviceName}/providers目录下写入自己的URL地址,这个操作就完成了服务的发布。 服务消费者启动的时候,订阅/dubbo/${serviceName}/providers目录下的提供者URL地址, 并向/dubbo/${serviceName} /consumers目录下写入自己的URL地址。 注意,所有向ZK上注册的地址都是临时节点,这样就能够保证服务提供者和消费者能够自动感应资源的变化。 另外,Dubbo还有针对服务粒度的监控,方法是订阅/dubbo/${serviceName}目录下所有提供者和消费者的信息。

  • 分布通知/协调

    ZooKeeper中特有watcher注册与异步通知机制,能够很好的实现分布式环境下不同系统之间的通知与协调,实现对数据变更的实时处理。使用方法通常是不同系统都对ZK上同一个znode进行注册,监听znode的变化(包括znode本身内容及子节点的),其中一个系统update了znode,那么另一个系统能够收到通知,并作出相应处理。

    应用:

    • 另一种心跳检测机制:检测系统和被检测系统之间并不直接关联起来,而是通过ZK上某个节点关联,大大减少系统耦合。

    • 另一种系统调度模式:某系统由控制台和推送系统两部分组成,控制台的职责是控制推送系统进行相应的推送工作。管理人员在控制台作的一些操作,实际上是修改了ZK上某些节点的状态,而ZK就把这些变化通知给他们注册Watcher的客户端,即推送系统,于是,作出相应的推送任务。

    • 另一种工作汇报模式:一些类似于任务分发系统,子任务启动后,到ZK来注册一个临时节点,并且定时将自己的进度进行汇报(将进度写回这个临时节点),这样任务管理者就能够实时知道任务进度。

      总之,使用zookeeper来进行分布式通知和协调能够大大降低系统之间的耦合。

  • 分布式锁

    共享锁在同一个进程中很容易实现,但是在跨进程或者在不同 Server 之间就不好实现了。Zookeeper 却很容易实现这个功能,实现方式也是需要获得锁的 Server 创建一个 EPHEMERAL_SEQUENTIAL 目录节点,然后调用 getChildren方法获取当前的目录节点列表中最小的目录节点是不是就是自己创建的目录节点,如果正是自己创建的,那么它就获得了这个锁,如果不是那么它就调用 exists(String path, boolean watch) 方法并监控 Zookeeper 上目录节点列表的变化,一直到自己创建的节点是列表中最小编号的目录节点,从而获得锁,释放锁很简单,只要删除前面它自己所创建的目录节点就行了。
    这里写图片描述

  • 集群管理

    集群机器监控

    这通常用于那种对集群中机器状态,机器在线率有较高要求的场景,能够快速对集群中机器变化作出响应。这样的场景中,往往有一个监控系统,实时检测集群机器是否存活。过去的做法通常是:监控系统通过某种手段(比如ping)定时检测每个机器,或者每个机器自己定时向监控系统汇报"我还活着"。 这种做法可行,但是存在两个比较明显的问题:① 集群中机器有变动的时候,牵连修改的东西比较多。② 有一定的延时。利用ZooKeeper中两个特性,就可以实施另一种集群机器存活性监控系统:① 客户端在节点x上注册一个Watcher,那么如果x的子节点变化了,会通知该客户端。② 创建EPHEMERAL类型的节点,一旦客户端和服务器的会话结束或过期,那么该节点就会消失。

    Master选举:

    Master选举则是zookeeper中最为经典的使用场景了,在分布式环境中,相同的业务应用分布在不同的机器上,有些业务逻辑,例如一些耗时的计算,网络I/O处,往往只需要让整个集群中的某一台机器进行执行,其余机器可以共享这个结果,这样可以大大减少重复劳动,提高性能,于是这个master选举便是这种场景下的碰到的主要问题。利用ZooKeeper中两个特性,就可以实施另一种集群中Master选举:① 利用ZooKeeper的强一致性,能够保证在分布式高并发情况下节点创建的全局唯一性,即:同时有多个客户端请求创建 /Master 节点,最终一定只有一个客户端请求能够创建成功。利用这个特性,就能很轻易的在分布式环境中进行集群选举了。②另外,这种场景演化一下,就是动态Master选举。这就要用到 EPHEMERAL_SEQUENTIAL类型节点的特性了,这样每个节点会自动被编号。允许所有请求都能够创建成功,但是得有个创建顺序,每次选取序列号最小的那个机器作为Master 。
  • 队列管理

    Zookeeper 可以处理两种类型的队列:

    ① 当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达,这种是同步队列。

    ② 队列按照 FIFO 方式进行入队和出队操作,例如实现生产者和消费者模型。

    (1) 同步队列用 Zookeeper 实现的实现思路如下:

    创建一个父目录 /synchronizing,每个成员都监控标志位目录 /synchronizing/start 是否存在,然后每个成员都加入这个队列,加入队列的方式就是创建 /synchronizing/member_i 的临时目录节点,然后每个成员获取 / synchronizing 目录的所有目录节点,也就是 member_i。判断 i 的值是否已经是成员的个数,如果小于成员个数等待 /synchronizing/start 的出现,如果已经相等就创建 /synchronizing/start。
    流程如下
    这里写图片描述

这里介绍了一下zookeeper是干什么的,一般应用场景是什么样,后面咱们接着学习zk怎么使用