一、Zookeeper简介
1、Zookeeper是什么
Zookeeper是Hadoop的正式子项目,它是一个针对大型分布式系统的可靠协调系统,它提供的功能包括:配置维护、名字服务、分布式同步、组服务等。Zookeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。
Ø Zookeeper 是 Google 的 Chubby一个开源的实现,是 Hadoop 的分布式协调服务。
Ø 它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务、配置维护和命名服务等。
2、为什么要使用Zookeeper
Ø 大部分分布式应用需要一个主控、协调器或控制器来管理物理分布的子进程(如资源、任务分配等)。
Ø 目前,大部分应用需要开发私有的协调程序,缺乏一个通用的机制。
Ø 协调程序的反复编写浪费,且难以形成通用、伸缩性好的协调器。
Ø ZooKeeper:提供通用的分布式锁服务,用以协调分布式应用。
3、Zookeeper能帮我们做什么
Ø 在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集群环境。
2、Zookeeper集群安装步骤
(以下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角色与选举
1、Zookeeper角色分类
Ø 领导者(Leader),负责进行投票的发起和决议,更新系统状态
Ø 学习者(learner),包括跟随者(Follower)和观察者(obServer),Follower用于接受客户端请求并向客户端返回结果,在选主过程中参与投票
Ø ObServer可以接受客户端连接,将写请求转发给Leader,但obServer不参加投票过程,只同步Leader的状态,obServer的目的是为了扩展系统,提高读取速度
Ø 客户端(Client),请求发起方
2、Leader选举过程
Ø 每个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原理与结构
1、Zookeeper工作原理
Ø 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对于应用最重要的特性,通过这个特性可以实现的功能包括配置的集中管理,集群管理,分布式锁等等。
3、Zookeeper节点
Ø 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开发操作
1、ZooKeeper命令行的使用
在成功启动后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命令删除节点
2、ZooKeeper 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作为一个用于协调分布式程序的服务,必将在更多的场合发挥越来越重要的作用。