Zookeeper学习整理

一、概述

1.1 概述

Zookeeper 是一个开源的分布式的,为分布式应用提供协调服务的 Apache 项目。
1)Zookeeper:一个领导者(leader),多个跟随者(follower)组成的集群。
2)Leader负责进行投票的发起和决议,更新系统状态。
3)Follower用于接收客户请求并向客户端返回结果,在选举Leader过程中参与投票。
4)集群中只要有半数以上节点存活,Zookeeper集群就能正常服务。
5)全局数据一致:每个server保存一份相同的数据副本,client无论连接到哪个server,数据都是一致的。
6)更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行。
7)数据更新原子性,一次数据更新要么成功,要么失败。
8)实时性,在一定时间范围内,client能读到最新数据。

1.2 应用场景

统一命名服务
在分布式环境下,经常需要对应用/服务进行统一命名,便于识别不同服务。
(1)类似于域名与ip之间对应关系,ip不容易记住,而域名容易记住。
(2)通过名称来获取资源或服务的地址,提供者等信息。
统一配置管理
1)分布式环境下,配置文件管理和同步是一个常见问题。
(1)一个集群中,所有节点的配置信息是一致的,比如Hadoop集群。
(2)对配置文件修改后,希望能够快速同步到各个节点上。
2)配置管理可交由ZooKeeper实现。
(1)可将配置信息写入ZooKeeper上的一个Znode。
(2)各个节点监听这个Znode。
(3)一旦Znode中的数据被修改,ZooKeeper将通知各个节点。
统一集群管理
1)分布式环境中,实时掌握每个节点的状态是必要的。
(1)可根据节点实时状态做出一些调整。
2)可交由ZooKeeper实现。
(1)可将节点信息写入ZooKeeper上的一个Znode。
(2)监听这个Znode可获取它的实时状态变化。
3)典型应用
(1)HBase中Master状态监控与选举。
服务器节点动态上下线
软负载均衡

二、内部工作原理

2.1 选举机制

1)半数机制(Paxos协议):集群中半数以上机器存活,集群可用。所以zookeeper适合装在奇数台机器上(便于投票)。
2)Zookeeper虽然在配置文件中并没有指定master和slave。但是,zookeeper工作时,是有一个节点为leader,其他则为follower,Leader是通过内部的选举机制临时产生的。

2.2 节点类型

1)Znode有两种类型:
短暂(ephemeral):客户端和服务器端断开连接后,创建的节点自己删除
持久(persistent):客户端和服务器端断开连接后,创建的节点不删除
2)Znode有四种形式的目录节点(默认是persistent)
(1)持久化目录节点(PERSISTENT)客户端与zookeeper断开连接后,该节点依旧存在。
(2)持久化顺序编号目录节点(PERSISTENT_SEQUENTIAL)客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号。
(3)临时目录节点(EPHEMERAL)客户端与zookeeper断开连接后,该节点被删除。
(4)临时顺序编号目录节点(EPHEMERAL_SEQUENTIAL)客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号。
3)创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护
4)在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过
顺序号推断事件的顺序

2.3 stat结构体

可以通过stat或者ls2命令查看znode的统计结构

[zk: localhost:2181(CONNECTED) 2] stat /
cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x20000000b
cversion = 5
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 3

1)czxid-引起这个znode创建的zxid,创建节点的事务的zxid每次修改ZooKeeper状态都会收到一个zxid形式的时间戳,也就是ZooKeeper事务ID。事务ID是ZooKeeper中所有修改总的次序。每个修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1在zxid2之前发生。
2)ctime-znode被创建的毫秒数(从1970年开始)
3)mzxid-znode最后更新的zxid
4)mtime-znode最后修改的毫秒数(从1970年开始)
5)pZxid-znode最后更新的子节点zxid
6)cversion-znode子节点变化号,znode子节点修改次数
7)dataversion-znode数据变化号
8)aclVersion-znode访问控制列表的变化号
9)ephemeralOwner-如果是临时节点,这个是znode拥有者的session id。如果不是临时节点则是0。
10)dataLength-znode的数据长度
11)numChildren-znode子节点数量

2.4 监听器原理

Zookeeper学习整理_第1张图片
监听原理详解
1)首先要有一个main()线程
2)在main线程中创建Zookeeper客户端,这时就会创建两个线程,一个负责
网络连接通信(connet),一个负责监听(listener)。
3)通过connect线程将注册的监听事件发送给Zookeeper。
4)在Zookeeper的注册监听器列表中将注册的监听事件添加到列表中。
5)Zookeeper监听到有数据或路径变化,就会将这个消息发送给listener线程。
6)listener线程内部调用了process()方法。
常见的监听
1)监听节点数据的变化:getpath[watch]
2)监听子节点增减的变化:lspath[watch]

2.5 写数据流程

1)Client向ZooKeeper的Server1上写数据,发送一个写请求;
2)如果Server1不是Leader,那么Server1会把接受到的请求进一步转发给Leader,因为每个ZooKeeper的Server里面有一个是Leader。这个Leader会将写请求广播给各个Server,比如Server1和Server2,各个Server写成功后就会通知Leader;
3)当Leader收到大多数Server数据写成功了,那么就说明数据写成功了。如果这里三个节点的话,只要有两个节点数据写成功了,那么就认为数据写成功了。写成功之后,Leader会告诉Server1数据写成功了。
4)Server1会进一步通知Client数据写成功了,这时就认为整个写操作成功。ZooKeeper整个写数据流程就是这样的。

三、常用操作

3.1 服务操作

配置zoo.cfg文件
具体配置

dataDir=/opt/module/zookeeper-3.4.10/zkData

增加如下配置

#######################cluster##########################
server.2=hadoop2:2888:3888
server.3=hadoop3:2888:3888
server.4=hadoop4:2888:3888

配置参数解读:
Server.A=B:C:D。
A是一个数字,表示这个是第几号服务器(与下面myid相同);
B是这个服务器的ip地址;
C是这个服务器与集群中的Leader服务器交换信息的端口;
D是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的
Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
配置myid
在/opt/module/zookeeper-3.4.14/zkData目录下创建一个myid的文件
#touch myid
文件中添加与上文中server对应的编号,如:2
常用命令

#bin/zkServer.sh start             //启动服务
#bin/zkServer.sh stop            //关闭服务
#bin/zkServer.sh status        //查看服务状态

3.2 客户端操作

启动客户端
bin/zkCli.sh

命令基本语法 功能描述
help 显示所有操作命令
ls path [watch] 使用ls命令来查看当前znode中所包含的内容
ls2 path [watch] 查看当前节点数据并能看到更新次数等数据
create 普通创建
-s 含有序列
-e 临时
get path [watch] 获得节点的值
set 设置节点的具体值
stat 查看节点状态
delete 删除节点
rmr 递归删除节点

3.3 API操作

3.3.1Elipse换件搭建

1.创建工程
2.寻找zookeeper安装文件zookeeper-3.4.14.tar.gz解压并将所有jar包导入工程lib中,build path。
3.拷贝log4j.properties到项目根目录//用于查看日志

3.3.2 项目代码


    //选择zkServer
	private String connectString="hadoop2:2181,hadoop3:2181,hadoop4:2181";
	//超时时间设置
	private static int sessionTimeout=30000;
	ZooKeeper zkClient;
	
//初始化客户端
	public void initClient() throws IOException{
	    //初始化zookeeper需要三个参数(选择连接、超市设置、是否观察)
		zkClient=new ZooKeeper(connectString, sessionTimeout, new Watcher(){
			@Override
			public void process(WatchedEvent event) {
				System.out.println(event.getType()+"\t"+event.getPath());
			}		
		});	
	}
//创建子节点
	public void create() throws KeeperException, InterruptedException{
		//创建节点,四个属性依次为:子节点目录、子节点内容、子节点权限、子节点类型
		//方法返回值为String类型,为创建节点的目录
		String path=zkClient.create("/zyp", "zhouyanpeng".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
		System.out.println(path);
	}
//获取子节点	
     publicvoidgetChildren()throwsException {
           List children = zkClient.getChildren("/",true);
          for(String child : children) {
               System.out.println(child);
          }
         //延时阻塞
        Thread.sleep(Long.MAX_VALUE);
}

//判断子节点是否存在
   publicvoidexist()throwsException {
        Stat stat = zkClient.exists("/eclipse",false);
        System.out.println(stat ==null? "not exist" : "exist");
   }

你可能感兴趣的:(Hadoop)