走向云计算之Zookeeper简介和使用场景

一、概述

Zookeeper是一个针对大型分布式系统的可靠协调系统;提供的功能包括:配置维护、名字服务、分布式同步、组服务等;目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户;Zookeeper已经成为Hadoop生态系统中的基础组件。ZooKeeper性能上的特点决定了它能够用在大型的、分布式的系统当中。从可靠性方面来说,它并不会因为一个节点的错误而崩溃。除此之外,它严格的序列访问控制意味着复杂的控制原语可以应用在客户端上。ZooKeeper在一致性、可用性、容错性的保证,也是ZooKeeper的成功之处,它获得的一切成功都与它采用的协议——Zab协议是密不可分的。
Zookeeper具有以下特点:

  • 最终一致性:为客户端展示同一视图,这是zookeeper最重要的功能。
  • 可靠性:如果消息被到一台服务器接受,那么它将被所有的服务器接受。
  • 实时性:Zookeeper不能保证两个客户端能同时得到刚更新的数据,如果需要最新数据,应该在读数据之前调用sync()接口。
  • 等待无关(wait-free):慢的或者失效的client不干预快速的client的请求。
  • 原子性:更新只能成功或者失败,没有中间状态。
  • 顺序性:所有Server,同一消息发布顺序一致。

正是因为Zookeeper的这些特点,使得它十分适合分布式集群的管理,在如下技术中都有Zookeeper的身影。

  • HDFS
  • YARN
  • Storm
  • HBase
  • Flume
  • Dubbo(阿里巴巴)
  • metaq阿里巴巴)

二、Zookeeper基本原理

1、Zookeeper架构

Zookeeper的基本架构如下:
走向云计算之Zookeeper简介和使用场景
该架构具有如下特点:

  • 每个Server在内存中存储了一份数据;
  • Zookeeper启动时,将从实例中选举一个leader(采用Paxos协议);
  • Leader负责处理数据更新等操作(采用Zab协议);
  • 一个更新操作成功,当且仅当大多数Server在内存中成功修改数据。

2、Zookeeper中的角色

Zookeeper中包含以下角色:
走向云计算之Zookeeper简介和使用场景
其中的ObServer是3.3.0版本的新增角色,主要基于如下考虑:Zookeeper需要保证高可用和强一致性,为了支持更多的客户端,就需要增加更多Server;但是的Server增多,导致投票阶段延迟增大,影响性能。为了权衡伸缩性和高吞吐率,引入Observer,Observer不参与投票;但是Observers接受客户端的连接,并将写请求转发给leader节点;加入更多Observer节点,可以提高伸缩性,同时不影响吞吐率。

3、Zookeeper Server的数目

首先我们知道Leader选举算法采用了Paxos协议;Paxos核心思想:当多数Server写成功,则任务数据写成功。例如:

  • 如果有3个Server,则2个写成功即可;
  • 如果有4或5个Server,则3个写成功即可。

因为以上特点,Zookeeper的Server数目一般为奇数(3、5、7)

  • 如果有3个Server,则最多允许1个Server挂掉;另外两个正常工作时也可以写入成功。
  • 如果有4个Server,则同样最多允许1个Server挂掉。如果有两个server挂掉,则无法构成多数server写成功的条件。

既然采用3或者4个server时都只允许挂掉一个server,为啥要用4个Server呢?其他同理,所以尽量使Zookeeper的server数目为奇数。

4、Zookeeper的数据模型

ZooKeeper拥有一个层次的命名空间,这个和标准的文件系统非常相似,如下图所示。
走向云计算之Zookeeper简介和使用场景
从图中我们可以看出ZooKeeper的数据模型,在结构上和标准文件系统的非常相似,都是采用这种树形层次结构,ZooKeeper树中的每个节点被称为—Znode。

  • 层次化的目录结构,命名符合常规文件系统规范;
  • 每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识;
  • 节点Znode可以包含数据和子节点(EPHEMERAL类型的节点不能有子节点);
  • Znode中的数据可以有多个版本,比如某一个路径下存有多个数据版本,那么查询这个路径下的数据需带上版本;
  • 客户端应用可以在节点上设置监视器(Watcher);
  • 节点不支持部分读写,而是一次性完整读写。

Znode有两种类型,短暂的(ephemeral)和持久(persistent)。Znode的类型在创建时确定并且之后不能再修改;短暂znode的客户端会话结束时,zookeeper会将该短暂znode删除,短暂znode不可以有子节点。持久znode不依赖于客户端会话,只有当客户端明确要删除该持久znode时才会被删除。

三、Zookeeper应用场景

1、统一命名服务

分布式环境下,经常需要对应用/服务进行统一命名,便于识别不同服务;类似于域名与ip之间对应关系,域名容易记住;通过名称来获取资源或服务的地址,提供者等信息;按照层次结构组织服务/应用名称。对于这种要求,可将服务名称以及地址信息写到Zookeeper上,客户端通过Zookeeper获取可用服务列表类。

2、配置管理

分布式环境下,配置文件管理和同步是一个常见问题;

  • 一个集群中,所有节点的配置信息是一致的,比如Hadoop;
  • 对配置文件修改后,希望能够快速同步到各个节点上

以上情形我们可以配置管理可交由Zookeeper实现;

  • 可将配置信息写入Zookeeper的一个znode上;
  • 各个节点监听这个znode;
  • 一旦znode中的数据被修改,zookeeper将通知各个节点。

3、集群管理

分布式环境中,实时掌握每个节点的状态是必要的;

  • 可根据节点实时状态作出一些调整;
  • 可交由Zookeeper实现;

对于上述情境,可将节点信息写入Zookeeper的一个znode上,监听这个znode可获取它的实时状态变化。典型应用:Hbase中Master状态监控与选举。

4、分布式通知/协调

分布式环境中,经常存在一个服务需要知道它所管理的子服务的状态;

  • NameNode须知道各DataNode的状态
  • JobTracker须知道各TaskTracker的状态

这其中我们的心跳检测机制可通过Zookeeper实现;信息推送也可由Zookeeper实现(发布/订阅模式)。

5、分布式锁

Zookeeper是强一致的,多个客户端同时在Zookeeper上创建相同znode,只有一个创建成功。
Zookeeper实现锁的独占性,多个客户端同时在Zookeeper上创建相同znode ,创建成功的那个客户端得到锁,其他客户端等待。
Zookeeper控制锁的时序,各个客户端在某个znode下创建临时znode (类型为CreateMode.EPHEMERAL_SEQUENTIAL),这样,该znode可掌握全局访问时序。

6、分布式队列

两种队列;

  • 当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达,这种是同步队列。
  • 队列按照 FIFO 方式进行入队和出队操作,例如实现生产者和消费者模型。(可通过分布式锁实现)

Zookeeper实现同步队列:

  • 一个job由多个task组成,只有所有任务完成后,job才运行完成。
  • 可为job创建一个/job目录,然后在该目录下,为每个完成的task创建一个临时znode,一旦临时节点数目达到task总数,则job运行完成。

四、ZooKeeper的分布式锁应用举例 

1、面临的问题

在分布式锁服务中,有一种最典型应用场景,就是通过对集群进行Master选举,来解决分布式系统中的单点故障。什么是分布式系统中的单点故障:通常分布式系统采用主从模式,就是一个主控机连接多个处理节点。主节点负责分发任务,从节点负责处理任务,当我们的主节点发生故障时,那么整个系统就都瘫痪了,那么我们把这种故障叫作单点故障。如下图所示:
走向云计算之Zookeeper简介和使用场景

2、传统解决方案

传统方式是采用一个备用节点,这个备用节点定期给当前主节点发送ping包,主节点收到ping包以后向备用节点发送回复Ack,当备用节点收到回复的时候就会认为当前主节点还活着,让他继续提供服务。如图所示:
走向云计算之Zookeeper简介和使用场景
当主节点挂了,这时候备用节点收不到回复了,然后他就认为主节点挂了接替他成为主节点如下图:
走向云计算之Zookeeper简介和使用场景
但是这种方式就是有一个隐患,就是网络问题,来看一网络问题会造成什么后果,如下图:
走向云计算之Zookeeper简介和使用场景
也就是说我们的主节点的并没有挂,只是在回复的时候网络发生故障,这样我们的备用节点同样收不到回复,就会认为主节点挂了,然后备用节点将他的Master实例启动起来,这样我们的分布式系统当中就有了两个主节点也就是—双Master,出现Master以后我们的从节点就会将它所做的事一部分汇报给了主节点,一部分汇报给了从节点,这样服务就全乱了。为了防止出现这种情况,我们引入了ZooKeeper,它虽然不能避免网络故障,但它能够保证每时每刻只有一个Master。我么来看一下ZooKeeper是如何实现的。

3 ZooKeeper解决方案

(1) Master启动
在引入了Zookeeper以后我们启动了两个主节点,”主节点-A”和”主节点-B”他们启动以后,都向ZooKeeper去注册一个节点。我们假设”主节点-A”锁注册地节点是”master-00001”,”主节点-B”注册的节点是”master-00002”,注册完以后进行选举,编号最小的节点将在选举中获胜获得锁成为主节点,也就是我们的”主节点-A”将会获得锁成为主节点,然后”主节点-B”将被阻塞成为一个备用节点。那么,通过这种方式就完成了对两个Master进程的调度。
走向云计算之Zookeeper简介和使用场景

(2) Master故障
如果”主节点-A”挂了,这时候他所注册的节点将被自动删除,ZooKeeper会自动感知节点的变化,然后再次发出选举,这时候”主节点-B”将在选举中获胜,替代”主节点-A”成为主节点。
走向云计算之Zookeeper简介和使用场景
(3) Master 恢复
如果主节点恢复了,他会再次向ZooKeeper注册一个节点,这时候他注册的节点将会是”master-00003”,ZooKeeper会感知节点的变化再次发动选举,这时候”主节点-B”在选举中会再次获胜继续担任”主节点”,”主节点-A”会担任备用节点。
走向云计算之Zookeeper简介和使用场景