Zookeeper的典型应用场景 -- 02

文章目录

    • 1.数据的发布和订阅 - 配置中心
    • 2.负载均衡
    • 3.命名服务 - 唯一命名
    • 4.分布式协调/通知
    • 5.集群管理
    • 6. Master选举
    • 7. 分布式锁
      • 7.1 排他锁
      • 7.2 共享锁
    • 8.分布式队列
    • 9.其他大型分布式系统中的应用

  Zookeeper是一个典型的发布/订阅模式的分布式数据管理与协调框架,可以使用它来进行分布式的发布和订阅。另外一方面,通过对Zookeeper中丰富的数据节点类型交叉使用,配置watcher事件机制,可以构建一系列分布式的核心功能,例如:数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举,分布式锁和分布式队列等。

1.数据的发布和订阅 - 配置中心

    数据发布与订阅,即所谓的配置中心,顾名思义就是发布者将数据发布到 ZooKeeper 节点上,
       供订阅者进行数据订阅,进而达到动态获取数据的目的,实现配置信息的集中式管理和动态更新。

    对于:数据量通常比较小。数据内容在运行时动态变化。集群中各机器共享,配置一致。
这样的全局配置信息就可以发布到 ZooKeeper上,让客户端(集群的机器)去订阅该消息。

发布/订阅系统一般有两种设计模式,分别是推(Push)和拉(Pull)模式。
      - 推模式
          服务端主动将数据更新发送给所有订阅的客户端
      - 拉模式
          客户端主动发起请求来获取最新数据,通常客户端都采用定时轮询拉取的方式

ZooKeeper 采用的是推拉相结合的方式:
    客户端想服务端注册自己需要关注的节点,一旦该节点的数据发生变更,那么服务端就会向相应
的客户端发送Watcher事件通知,客户端接收到这个消息通知后,需要主动到服务端获取最新的数据

  例如开发中经常有这样的需求:系统中需要使用一些通用的配置信息,例如机器列表信息,运行时的开关配置,数据库配置信息等。这些全局配置具备如下特点:

  • 数据量小
  • 数据通常在运行时发生变化
  • 集群中各机器共享,配置一致

2.负载均衡

例如DNS的配置,同样利用watcher事件来做。

3.命名服务 - 唯一命名

  ZooKeeper 的命名服务即生成全局唯一的ID。

  在传统的单库单表的情况下可以使用自增来实现表中唯一的ID,但是在多库多表的情况下就不能使用自增,当然可以使用UUID来实现唯一ID,然而UUID生成的字符串太长,存储也需要花费更多的时间。使用Zookeeper的顺序节点就可以创建一个全局的唯一ID

     命名服务也是分布式系统中比较常见的一类场景。在分布式系统中,通过使用命名服务,客户端
应用能够根据指定名字来获取资源或服务的地址,提供者等信息。被命名的实体通常可以是集群中的
机器,提供的服务,远程对象等等——这些我们都可以统称他们为名字。

    其中较为常见的就是一些分布式服务框架(如RPC)中的服务地址列表。通过在ZooKeeper里
创建顺序节点,能够很容易创建一个全局唯一的路径,这个路径就可以作为一个名字。

4.分布式协调/通知

    ZooKeeper 中特有 Watcher 注册与异步通知机制,能够很好的实现分布式环境下不同机器,
甚至不同系统之间的通知与协调,从而实现对数据变更的实时处理。使用方法通常是不同的客户端
如果 机器节点 发生了变化,那么所有订阅的客户端都能够接收到相应的Watcher通知,并做出相应
的处理。

ZooKeeper的分布式协调/通知,是一种通用的分布式系统机器间的通信方式。

5.集群管理

zookeeper节点有这两特性:

  • 客户端对某一个节点注册watcher监听,当该数据节点的内容或者子节点列表变更时,Zookeeper服务器会向订阅的客户端发送通知。
  • 对于Zookeeper创建的临时节点,一旦客户端和服务端直接会话xiaoshi消失,就自动将临时节点清除

利用Zookeeper上面的两个特性就可以实现另一种集群机器存活性监控系统(传统使用Agent方式来监控集群状态情况)。

6. Master选举

  利用Zookeeper的同级节点唯一性,强一致性来实现Master选举

  Master 选举可以说是 ZooKeeper 最典型的应用场景了。比如 HDFS 中 Active NameNode 的选举、YARN 中 Active ResourceManager 的选举和 HBase 中 Active HMaster 的选举等。

      针对 Master 选举的需求,通常情况下,我们可以选择常见的关系型数据库中的主键特性来
实现:希望成为 Master 的机器都向数据库中插入一条相同主键ID的记录,数据库会帮我们进行
主键冲突检查,也就是说,只有一台机器能插入成功——那么,我们就认为向数据库中成功插入数据
的客户端机器成为Master。

    依靠关系型数据库的主键特性确实能够很好地保证在集群中选举出唯一的一个Master。

    但是,如果当前选举出的 Master 挂了,那么该如何处理?谁来告诉我 Master 挂了呢?
显然,关系型数据库无法通知我们这个事件。但是,ZooKeeper 可以做到!

    利用 ZooKeepr 的强一致性,能够很好地保证在分布式高并发情况下节点的创建一定能够
保证全局唯一性,即 ZooKeeper 将会保证客户端无法创建一个已经存在的 数据单元节点。
    也就是说,如果同时有多个客户端请求创建同一个临时节点,那么最终一定只有一个客户端
请求能够创建成功。利用这个特性,就能很容易地在分布式环境中进行 Master 选举了。

    成功创建该节点的客户端所在的机器就成为了 Master。同时,其他没有成功创建该节点的
客户端,都会在该节点上注册一个子节点变更的 Watcher,用于监控当前 Master 机器是否存
活,一旦发现当前的Master挂了,那么其他客户端将会重新进行 Master 选举。

    这样就实现了 Master 的动态选举。

7. 分布式锁

分布式锁是控制分布式系统之间同步访问共享资源的一种方式
分布式锁又分为排他锁和共享锁两种

7.1 排他锁

定义锁
  ZooKeeper 上的一个 机器临时节点 可以表示一个锁。

获得锁
  把ZooKeeper上的一个节点看作是一个锁,获得锁就通过创建临时节点的方式来实现。

  ZooKeeper 会保证在所有客户端中,最终只有一个客户端能够创建成功,那么就可以 认为该客户端获得了锁。同时,所有没有获取到锁的客户端就需要到/exclusive_lock 节点上注册一个子节点变更的Watcher监听,以便实时监听到lock节点的变更情况。

释放锁
  因为锁是一个临时节点,释放锁有两种方式:

  • 当前获得锁的客户端机器发生宕机或重启,那么该临时节点就会被删除,释放锁
  • 正常执行完业务逻辑后,客户端就会主动将自己创建的临时节点删除,释放锁。

重新竞争锁
  无论在什么情况下移除了lock节点,ZooKeeper 都会通知所有在 /exclusive_lock 节点上注册了节点变更 Watcher 监听的客户端。这些客户端在接收到通知后,再次重新发起分布式锁获取,即重复『获取锁』过程。

7.2 共享锁

  根据共享锁的定义,不同的事务都可以同时对同一个数据对象进行读取操作,而更新必须在当前没有任何事务的时候才能进行。

定义锁
  ZooKeeper 上的一个 机器临时节点 利用 host+R/W(请求类型) + 序号可以表示一个锁。

获取锁
  在需要获取共享锁时,所有的客户端都会到/shared_lock节点下创建一个临时节点,如果是读请求创建/shared_lock/192.86.0.1-R-0000000001,这个节点就是共享锁创建如果是写请求 /shared_lock/192.86.0.1-W-0000000001

判断读写顺序如下4个步骤:

  • 1.创建完节点后,获取/shared_lock节点下所有的子节点,并对该节点注册子节点的变更Watcher监听

  • 2.确定自己的节点序号在子节点中的顺序。

  • 3.判断请求,执行锁的获取

  • 对于读请求:
    如果没有比自己序号小的的子节点,或者所有比自己序号小的子节点都是读请求,那么表明获取到了共享锁,同时开始执行读取逻辑;

    如果比自己序号小的子节点中有写请求,那么就需要进入等待。

    • 对于写请求:
      如果自己不是序号最小的子节点,那么就需要进入等待。
  • 4.接受到Watcher通知后,重复步骤1。

释放锁
  和排他锁一样。释放锁如下两种方式:

  • 当前获得锁的客户端机器发生宕机或重启,那么该临时节点就会被删除,释放锁
  • 正常执行完业务逻辑后,客户端就会主动将自己创建的临时节点删除,释放锁。

羊群效应:
  上面的共享锁只能满足一般的分布式集群竞争锁的需求,并且性能还可以的情况下—这里的场景指集群规模不大,一般在10台机器以内。

上面的读写顺序中第三个步骤中,当某一个机器释放锁后,它会用watcher通知所有的客户端。然后只有一个客户端会拿到锁,其他并没有什么用。
  客户端无端的接受到过多的和自己不相关的事件通知,这如果在集群规模大的时候,会对Server造成很大的性能影响,并且如果一旦同一时间有多个节点的客户端断开连接,这个时候,服务器就会像其余客户端发送大量的事件通知——这就是所谓的羊群效应。

解决羊群效应这个问题
  并不对所有的子节点都执行watcher事件监听,只对比自己小的序号执行watcher监听。

改写读写顺序如下4个步骤:

  • 1.创建完节点后,获取/shared_lock节点下所有的子节点;

  • 2.确定自己的节点序号在子节点中的顺序;

  • 3.判断请求,执行锁的获取

  • 对于读请求:
      如果没有比自己序号小的的子节点,或者所有比自己序号小的子节点都是读请求,那么表明获取到了共享锁,同时开始执行读取逻辑;

    如果比自己序号小的子节点中有写请求,那么就需要进入等待。那么对比自己小的序号注册watcher监听事件

    • 对于写请求:
      如果自己不是序号最小的子节点,那么就需要进入等待。对比自己小的序号注册watcher监听事件
  • 4.接受到Watcher通知后,重复步骤1。

8.分布式队列

除了常用的分布式队列-消息队列,ActiveMQ,kafka,RabbitMQ等。
  这里的队列可以使用Zookeeper实现,这里分为两种先进先出队列和等待所有队列元素聚集后同意安排执行的barrier模型。

原理:同样利用Zookeeper创建有序临时节点来实现,先进先出通过序号的顺序实现。
barrier分布式屏障,可以用设置临时节点的值为 需要达到队列的数量来实现。

9.其他大型分布式系统中的应用

例如Hadoop,Hbase,Kafka,

Zookeeper在阿里巴巴中的实践和应用:

  • RPC服务框架:dubbo,
  • 消息中间件:Metamorphosis,
  • 基于Mysql Binlog的增量订阅和消费组件:Canal
  • 分布式数据库同步系统:Otter
  • 轻量级分布式通用搜索平台:终搜
  • 实时计算引擎:JStorm

你可能感兴趣的:(zookeeper,应用场景)