分布式协调框架Zookeeper

一、Zookeeper简介

1Zookeeper是什么

Zookeeper是Hadoop的正式子项目,它是一个针对大型分布式系统的可靠协调系统,它提供的功能包括:配置维护、名字服务、分布式同步、组服务等。Zookeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。

Ø Zookeeper 是 Google 的 Chubby一个开源的实现,是 Hadoop 的分布式协调服务。

Ø 它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务、配置维护和命名服务等。

2、为什么要使用Zookeeper

Ø 大部分分布式应用需要一个主控、协调器或控制器来管理物理分布的子进程(如资源、任务分配等)。

Ø 目前,大部分应用需要开发私有的协调程序,缺乏一个通用的机制。

Ø 协调程序的反复编写浪费,且难以形成通用、伸缩性好的协调器。

Ø ZooKeeper:提供通用的分布式锁服务,用以协调分布式应用。

3Zookeeper能帮我们做什么

Ø 在Hadoop中,使用Zookeeper的事件处理确保整个集群只有一个NameNode,存储配置信息等。

Ø 在HBase中,使用Zookeeper的事件处理确保整个集群只有一个HMaster,察觉HRegionServer联机和宕机,存储访问控制列表等。

Ø 

4、ZooKeeper的应用

   ZooKeeper成功地应用于大量的工业程序中。它在Yahoo!被用作雅虎消息代理(Yahoo! Message Broker)的协调和故障恢复服务。雅虎消息代理是一个高度可扩展的发布-订阅系统,它管理着上千的总联机程序和信息控制系统,另外它还用于Yahoo!crawler获取服务并进行故障维护。除此之外,一些Yahoo!广告系统也同样使用了ZooKeeper来实现可靠的服务。

二、Zookeeper集群安装(在Hadoop集群上搭建)

1、安装前的技能准备

Ø 学习过宅客学院的《Hadoop大数据实践》课程。

Ø 掌握基本的Linux常用命令,了解Hadoop结构与原理、HBase原理与应用,能独立搭建Hadoop集群环境。

2Zookeeper集群安装步骤

  (以下Zookeeper简称zk):

  2.1 zk服务器集群规模不小于三个节点,在本集群中创建Hadoop0、Hadoop1

、Hadoop2,其中Hadoop0为主服务器,Hadoop1、Hadoop2为从服务器,并且要求各服务器之间系统时间要保持一致。

  2.2 下载ZooKeeper:http://labs.renren.com/apache-mirror/zookeeper/zookeeper-3.4.3/zookeeper-3.4.3.tar.gz

将下载的tar包拷贝到hadoop0的/usr/local目录下,解压缩zk的安装tar包

tar -xzvf ookeeper-3.4.3.tar.gz

并在/etc/profile设置环境变量:

export JAVA_HOME=usr/local/jdk

export HADOOP_HOME=usr/local/hadoop

export ZOOKEEPER_HOME=usr/local/zk

export PATH=.:$JAVA_HOME/bin:$HADOOP_HOME/bin

:$ZOOKEEPER_HOME/bin:$PATH

  2.3 在conf目录下,修改文件名 mv zoo_sample.cfg  zoo.cfg

  2.4 编辑该文件,执行vi zoo.cfg

修改dataDir=/usr/local/zk/data

只运行在一台服务器上,适合测试环境;Zookeeper 的启动脚本在 bin 目录下;在启动脚本之前,还有几个基本的配置项需要配置一下, 

tickTime :这个时间是作为 Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个  tickTime  时间就会发送一个心跳;

dataDir:顾名思义就是 Zookeeper 保存数据的目录,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里;

clientPort:这个端口就是客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。

当这些配置项配置好后,就可以启动 Zookeeper 了,启动后使用命令echo ruok | nc localhost 2181检查 Zookeeper 是否已经在服务

 

新增Server.0=hadoop0:2888:3888

     Server.1=hadoop1:2888:3888

     Server.2=hadoop2:2888:3888

注:Server.A=B:C:D:其中 A 是一个数字,表示这个是第几号服务器;B 是这个服务器的 ip 地址;C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。

2.5 创建文件夹data,命令:mkdir /usr/local/zk/data

2.6 在data目录下,创建文件myid,值为0

2.7 把zk目录复制到hadoop1和hadoop2中

    scp  -r  zk/  hadoop1:/usr/local

       复制配置文件profile:

    scp  /etc/profile  hadoop1:/etc/

        生成一下配置文件:

    ssh  hadoop1

    source  /etc/profile

2.8 把hadoop1中相应的myid的值改为1

    把hadoop2中相应的myid的值改为2

2.9 启动,在三个节点上分别执行命令zkServer.sh  start

2.10 检验,在三个节点上分别执行命令zkServer.sh  status

   分别在3台机器上启动ZooKeeper的Server:sh bin/zkServer.sh start;运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble)。Zookeeper通过复制来实现高可用性,只要集合体中半数以上的机器处于可用状态,它就能够保证服务继续。为什么一定要超过半数呢?这跟Zookeeper的复制策略有关:zookeeper确保对znode 树的每一个修改都会被复制到集合体中超过半数的机器上。

三、Zookeeper角色与选举

1Zookeeper角色分类

Ø 领导者(Leader),负责进行投票的发起和决议,更新系统状态

Ø 学习者(learner),包括跟随者(Follower)和观察者(obServer),Follower用于接受客户端请求并向客户端返回结果,在选主过程中参与投票

Ø ObServer可以接受客户端连接,将写请求转发给Leader,但obServer不参加投票过程,只同步Leader的状态,obServer的目的是为了扩展系统,提高读取速度

Ø 客户端(Client),请求发起方

2Leader选举过程

Ø 每个Server启动以后都询问其它的Server它要投票给谁。

Ø 对于其他Server的询问,Server每次根据自己的状态都回复自己推荐的Leader的id和上一次处理事务的zxid,(系统启动时每个Server都会推荐自己)

Ø 收到所有Server回复以后,就计算出zxid最大的哪个Server,并将这个Server相关信息设置成下一次要投票的Server。

Ø 计算的过程中获得票数最多的Server为获胜者,如果获胜者的票数超过半数,则此Server被选为Leader。否则,继续这个过程,直到Leader被选举出来。

Ø Leader就会开始等待Server连接

Ø Follower连接Leader,将最大的zxid发送给Leader

Ø Leader根据Follower的zxid确定同步点

Ø 完成同步后通知Follower 已经成为uptodate(现时)状态

Ø Follower收到uptodate消息后,又可以重新接受Client的请求进行服务了

n 选完Leader以后,zk就进入状态同步过程。

 

 

四、ZooKeeper原理与结构

1Zookeeper工作原理

Ø Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。

实现这个机制的协议叫做Zab协议。Zab协议有两种模式,它们分别是恢复模式和广播模式。当服务启动或者在领导者崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server 完成了和Leader的状态同步以后,恢复模式就结束了。状态同步保证了Leader和Server具有相同的系统状态。

Ø 一旦Leader已经和多数的Follower进行了状态同步后,他就可以开始广播消息了,即进入广播状态。这时候当一个Server加入Zookeeper服务中,它会在恢复模式下启动,发现Leader,并和Leader进行状态同步。待到同步结束,它也参与消息广播。Zookeeper服务一直维持在广播状态,直到Leader崩溃了或者Leader失去了大部分的Followers支持。

Ø 广播模式需要保证proposal (提议) 被按顺序处理,因此zk采用了递增的事务id号(zxid)来保证。所有的提议(proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识Leader关系是否改变,每次一个Leader被选出来,它都会有一个新的epoch。低32位是个递增计数。

Ø 当Leader崩溃或者Leader失去大多数的Follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的Leader,让所有的Server都恢复到一个正确的状态。

2、Zookeeper数据模型

 

Ø 层次化的目录结构,命名符合常规文件系统规范

Ø 每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识

Ø 节点Znode可以包含数据和子节点,但是EPHEMERAL类型的节点不能有子节点

Ø Znode中的数据可以有多个版本,比如某一个路径下存有多个数据版本,那么查询这个路径下的数据就需要带上版本

Ø 客户端应用可以在节点上设置监视器

Ø 节点不支持部分读写,而是一次性完整读写

Ø znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的集中管理,集群管理,分布式锁等等。

3Zookeeper节点

Ø Znode有两种类型,短暂的(ephemeral)和持久的(persistent)

Ø Znode的类型在创建时确定并且之后不能再修改

Ø 短暂znode的客户端会话结束时,zookeeper会将该短暂znode删除,短暂znode不可以有子节点

Ø 持久znode不依赖于客户端会话,只有当客户端明确要删除该持久znode时才会被删除

Ø Znode有四种形式的目录节点,PERSISTENT、PERSISTENT_SEQUENTIAL、EPHEMERAL、EPHEMERAL_SEQUENTIAL

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

Ø 如果 znode 是临时节点,这个 session 失效,znode 也就删除了,而对于持久化目录节点,这个目录节点存储的数据不会丢失;

Ø 顺序自动编号的目录节点,这种目录节点会根据当前已经存在的节点数自动加 1,然后返回给客户端已经成功创建的目录节点名;

对于临时目录节点,一旦创建这个节点的客户端与服务器端口 session 超时,这种节点会被自动删除;

 

五、Zookeeper开发操作

1ZooKeeper命令行的使用

在成功启动后ZooKeeper服务之后,输入下述命令,连接到 ZooKeeper服务:

zkCli.sh -server localhost:2181

连接成功后,系统会输出ZooKeeper的相关环境及配置信息,并在屏幕输出“Welcome to ZooKeeper”等信息。

输入help之后,屏幕会输出所有可用的ZooKeeper命令,如下图所示:

 

1)使用ls命令查看当前ZooKeeper中所包含的内容

 

2)使用create这个命令创建一个新的Znode节点

 

3)使用get命令确认第二步中所创建的Znode是否包含创建的字符串

 

4)通过set命令来对zk所关联的字符串进行设置

 

5)使用delete命令删除节点

 

2ZooKeeper API的使用

2.1 ZooKeeper API 简介

  ZooKeeper API共包含五个包,分别为:

org.apache.zookeeper、org.apache.zookeeper.data、org.apache.zookeeper.server

org.apache.zookeeper.server.quorum、org.apache.zookeeper.server.upgrade。

其中,org.apache.zookeeper包含ZooKeeper类,它是我们编程时最常用的类文件。

   这个类是ZooKeeper客户端库的主要类文件。如果要使用ZooKeeper服务,应用程序首先必须创建一个ZooKeeper实例,这时就需要使用此类。一旦客户端和ZooKeeper服务建立起了连接,ZooKeeper系统将会给此连接会话分配一个ID值,并且客户端将会周期性地向服务器发送心跳来维持会话的连接。只要连接有效,客户端就可以调用ZooKeeper API来做相应的处理。

2.2 ZooKeeper API接口

1) String create(String path, byte[] data, List<ACL> acl, CreateMode createMode) 

2) Stat exists(String path, boolean watch) 

3) void delete(String path, int version) 

4) List<String> getChildren(String path, boolean watch) 

5) List<String> getChildren(String path, boolean watch) 

6) Stat setData(String path, byte[] data, int version) 

7) byte[] getData(String path, boolean watch, Stat stat) 

8) void addAuthInfo(String scheme, byte[] auth) 

9) Stat setACL(String path, List<ACL> acl, int version) 

10) List<ACL> getACL(String path, Stat stat) 

2.3程序案例

这里通过一个例子来简单介绍如何使用ZooKeeper API编写自己的应用程序,代码如下:

package ZooKeeper;

import org.apache.zookeeper.CreateMode;

import org.apache.zookeeper.WatchedEvent;

import org.apache.zookeeper.Watcher;

import org.apache.zookeeper.ZooDefs.Ids;

import org.apache.zookeeper.ZooKeeper;

 

public class Demo {

private static final int SESSION_TIMEOUT=30000;

ZooKeeper zkKeeper;

//创建watcher实例

Watcher wh=new Watcher(){

 

@Override

public void process(WatchedEvent event) {

// TODO Auto-generated method stub

System.out.println(event.toString());

}

};

//初始化ZooKeeper实例

@SuppressWarnings("unused")

private void createZkInstance() throws Exception{

zkKeeper=new ZooKeeper("hadoop0:2181",Demo.SESSION_TIMEOUT,this.wh);

}

//ZNode节点进行操作

@SuppressWarnings("unused")

private void ZkOperations() throws Exception{

System.out.println("创建节点");

zkKeeper.create("/zk","myData".getBytes(),Ids.OPEN_ACL_UNSAFE , CreateMode.PERSISTENT);

System.out.println("查看是否创建成功");

System.out.println(new String(zkKeeper.getData("/zk", false, null)));

System.out.println("修改节点数据");

zkKeeper.setData("/zk", "hello you".getBytes(), -1);

System.err.println("查看是否修改成功:");

System.out.println(new String(zkKeeper.getData("/zk", false, null)));

System.out.println("删除节点");

zkKeeper.delete("/zk", -1);

System.out.println("查看节点是否被删除");

System.out.println("节点状态:【"+zkKeeper.exists("/zk", false)+"");

}

//关闭ZK

@SuppressWarnings("unused")

private void zkClose() throws Exception{

zkKeeper.close();

}

public static void main(String[] args) throws Exception {

Demo demo=new Demo();

demo.createZkInstance();

demo.ZkOperations();

demo.zkClose();

}

}

运行结果如下:

 

六、ZooKeeper总结

1、综上所述,Zookeeper具有许多特性,简单概括如下:

Ø Zookeeper是简单的

Ø Zookeeper是富有表现力的

Ø Zookeeper具有高可用性

Ø Zookeeper采用松耦合交互方式

Ø Zookeeper是一个丰富的资源库

  ZooKeeper作为Hadoop项目的一个子项目,是Hadoop集群管理中一个必不可少的模块。它主要用来控制集群中的数据,如管理Hadoop集群中的NameNode,以及Hbase中的Master Election、Server之间的状态同步等。ZooKeeper作为一个用于协调分布式程序的服务,必将在更多的场合发挥越来越重要的作用。

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值