Hadoop -- ZooKeeper

1. 什么是ZooKeeper?

ZooKeeper 就是动物园管理员,他是用来管 hadoop(大象)、Hive(蜜蜂)等的管理员。

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Hadoop、Hbase、kafka、dubbo等重要组件。

ZooKeeper是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。ZooKeeper包含一个简单的原语集,提供Java和C的接口。

简单来说,ZooKeeper有两个功能:管理数据+监听数据

2. 管理数据

管理数据就得有一个结构对数据进行存储,然后才能进行数据的增删改查。
在这里插入图片描述
zookeeper 中的数据是按照“树”结构进行存储的,根目录下有多个子目录,子目录下还可以创建/删除子目录;每个子目录项如 NameService 都被称作为 znode(目录节点),和文件系统一样,能够自由的增加、删除znode,唯一的不同在于znode是可以存储数据的。

节点类型:
(1)PERSISTENT 持久化节点: 所谓持久节点,是指在节点创建后,就一直存在,直到 有删除操作来主动清除这个节点。否则不会因为创建该节点的客户端会话失效而消失。

(2)PERSISTENT_SEQUENTIAL 持久顺序节点:这类节点的基本特性和上面的节点类 型是一致的。额外的特性是,在 ZK 中,每个父节点会为他的第一级子节点维护一份时序, 会记录每个子节点创建的先后顺序。基于这个特性,在创建子节点的时候,可以设置这个属 性,那么在创建节点过程中,ZK 会自动为给定节点名加上一个数字后缀,作为新的节点名。 这个数字后缀的范围是整型的最大值。 在创建节点的时候只需要传入节点 “/test_”,这样 之后,zookeeper 自动会给”test_”后面补充数字。

(3)EPHEMERAL 临时节点:和持久节点不同的是,临时节点的生命周期和客户端会话绑定。也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉。注意,这里提到的是会话失效,而非连接断开。另外,在临时节点下面不能创建子节点。 这里还要注意一件事,就是当你客户端会话失效后,所产生的节点也不是一下子就消失了,也要过一段时间,大概是 10 秒以内,可以试一下,本机操作生成节点,在服务器端用 命令来查看当前的节点数目,你会发现客户端已经 stop,但是产生的节点还在。

(4) EPHEMERAL_SEQUENTIAL 临时自动编号节点:此节点是属于临时节点,不过带 有顺序,客户端会话结束节点就消失。

3. 监听数据

客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。

4. 集群中的角色

在这里插入图片描述

5. Java客户端

不注册监听

package zookeeper.demo;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.junit.Before;
import org.junit.Test;

public class ClientDemo {
	ZooKeeper zk = null;
	
	@Before
	// 新建一个客户端对象
	public void init() throws IOException{
		// 参数1:连接的zookeeper地址(最好写多台),参数2:会话超时时间
		// 参数3:接口实现类;当监听发生时,zookeeper会告知客户端,此时客户端需要做逻辑处理,这里传的参数就是接口的实现类,里面具体写实现的逻辑
		zk = new ZooKeeper("hadoop100:2181,hadoop101:2181,hadoop102:2181", 2000, null);
	}
	
	@Test
	// 创建节点
	public void testCreate() throws KeeperException, InterruptedException{
		// 参数1:节点路径          参数2:数据         参数3:访问权限           参数4:节点类型(持久、短暂、有序或 组合类型)
		String create = zk.create("/eclipse", "hello".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
		System.out.println(create);
		zk.close();
	}
	
	@Test
	// 更新节点数据
	public void testUpdate() throws UnsupportedEncodingException, KeeperException, InterruptedException{
		// 1:节点路径, 2:数据, 3:要修改的数据版本,-1代表修改任意版本为最新数据
		zk.setData("/eclipse", "我爱你".getBytes("UTF-8"), -1);
		zk.close();
	}
	
	@Test
	// 查看节点的数据内容
	public void testGet() throws Exception{
		// 1:节点路径, 2:是否需要监听, 3:获取的数据的版本,null表示获取最新版本
		byte[] data = zk.getData("/eclipse", false, null);
		System.out.println(new String(data,"utf-8"));
		zk.close();
	}
	
	@Test
	// 查看该节点下有什么子节点
	public void testListChildren() throws Exception, InterruptedException{
		List<String> children = zk.getChildren("/eclipse", false);
		for (String child : children) {
			System.out.println(child);
		}
		zk.close();
	}
	
	@Test
	// 删除节点
	public void testRm() throws InterruptedException, KeeperException{
		zk.delete("/eclipse", -1);
		zk.close();
	}
}

注册监听

package zookeeper.demo;

import java.io.IOException;

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;
import org.junit.Before;
import org.junit.Test;

public class WatcherDemo {
	ZooKeeper zk = null;

	@Before
	public void init() throws IOException {
		// 参数1:连接的zookeeper地址(最好写多台),参数2:会话超时时间
		// 参数3:接口实现类;当监听发生时,zookeeper会告知客户端,此时客户端需要做逻辑处理,这里传的参数就是接口的实现类,里面具体写实现的逻辑
		zk = new ZooKeeper("hadoop100:2181,hadoop101:2181,hadoop102:2181",
				2000, new Watcher() {
					@Override
					public void process(WatchedEvent event) {
						// TODO Auto-generated method stub
						if (event.getState() == KeeperState.SyncConnected && event.getType() == EventType.NodeDataChanged) {
							System.out.println(event.getPath());
							System.out.println(event.getType());
							System.out.println("节点数据的监听事件发生了...");
							
							// 反复监听
							try {
								zk.getData("/eclipse", true, null);
							} catch (KeeperException | InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
					}

				});
	}

	@Test
	public void testGet() throws Exception {
		// 1:节点路径, 2:是否需要监听, 3:获取的数据的版本,null表示获取最新版本
		byte[] data = zk.getData("/eclipse", true, null);
		System.out.println(new String(data, "utf-8"));
		Thread.sleep(Long.MAX_VALUE);
	}
}

参考:https://my.oschina.net/u/3796575/blog/1845035

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值