4.1 分布式安装部署

0)集群规划

在hadoop2、hadoop3和hadoop4三个节点上部署Zookeeper。

1)解压安装

(1)解压zookeeper安装包到/opt/module/目录下

[atguigu@hadoop102 software]$ tar -zxvf zookeeper-3.4.10.tar.gz -C /opt/module/

(2)在/opt/module/zookeeper-3.4.10/这个目录下创建data/zkData

mkdir -p data/zkData

(3)重命名/opt/module/zookeeper-3.4.10/conf这个目录下的zoo_sample.cfg为zoo.cfg

mv zoo_sample.cfg zoo.cfg

2)配置zoo.cfg文件

(1)具体配置

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

增加如下配置

#######################cluster##########################

server.2=hadoop102:2888:3888

server.3=hadoop103:2888:3888

server.4=hadoop104:2888:3888

这里配置了三个server节点,hadoop102 103 104 主机名,2888 leader和flower之间通信的端口号,3888,leader挂掉了之后重新选举leader,之间通信的端口号。

(2)配置参数解读

Server.A=B:C:D。

A是一个数字,表示这个是第几号服务器;

B是这个服务器的ip地址;

C是这个服务器与集群中的Leader服务器交换信息的端口;

D是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口。

集群模式下配置一个文件myid,这个文件在dataDir目录下,这个文件里面有一个数据就是A的值,Zookeeper启动时读取此文件,拿到里面的数据与zoo.cfg里面的配置信息比较从而判断到底是哪个server。

注意:每个机器的myid是不一样的,应该修改为自己对应的。

3)集群操作

(1)在/opt/module/zookeeper-3.4.10/data/zkData目录下创建一个myid的文件

touch myid

添加myid文件,注意一定要在linux里面创建,在notepad++里面很可能乱码

(2)编辑myid文件

vi myid

在文件中添加与server对应的编号:如2

(3)拷贝配置好的zookeeper到其他机器上

scp -r zookeeper-3.4.10/ root@hadoop3.atguigu.com:/opt/app/

scp -r zookeeper-3.4.10/ root@hadoop4.atguigu.com:/opt/app/

并分别修改myid文件中内容为3、4

(4)分别启动zookeeper

[root@hadoop2 zookeeper-3.4.10]# bin/zkServer.sh start

[root@hadoop3 zookeeper-3.4.10]# bin/zkServer.sh start

[root@hadoop4 zookeeper-3.4.10]# bin/zkServer.sh start

(5)查看状态

[root@hadoop2 zookeeper-3.4.10]# bin/zkServer.sh status

JMX enabled by default

Using config: /opt/module/zookeeper-3.4.10/bin/…/conf/zoo.cfg

Mode: follower

[root@hadoop3 zookeeper-3.4.10]# bin/zkServer.sh status

JMX enabled by default

Using config: /opt/module/zookeeper-3.4.10/bin/…/conf/zoo.cfg

Mode: leader

[root@hadoop4 zookeeper-3.4.5]# bin/zkServer.sh status

JMX enabled by default

Using config: /opt/module/zookeeper-3.4.10/bin/…/conf/zoo.cfg

Mode: follower

4.2 客户端命令行操作

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

1)启动客户端

[atguigu@hadoop103 zookeeper-3.4.10]$ bin/zkCli.sh

2)显示所有操作命令

[zk: localhost:2181(CONNECTED) 1] help

3)查看当前znode中所包含的内容

[zk: localhost:2181(CONNECTED) 0] ls /

[zookeeper]

4)查看当前节点数据并能看到更新次数等数据(查看非常详细的详情)

[zk: localhost:2181(CONNECTED) 1] ls2 /

[zookeeper]

cZxid = 0x0 (事物创建的编号)

ctime = Thu Jan 01 08:00:00 CST 1970 (创建的时间)

mZxid = 0x0 (事物id)

mtime = Thu Jan 01 08:00:00 CST 1970 (节点最后的时间)

pZxid = 0x0

cversion = -1 (创建时候的版本)

dataVersion = 0 (子节点的版本)

aclVersion = 0(权限的版本)

ephemeralOwner = 0x0 (是否是短暂节点)

dataLength = 0(数据的长度)

numChildren = 1(子节点的个数)

5)创建普通节点

[zk: localhost:2181(CONNECTED) 2] create /app1 “hello app1” (第一个参数,创建的目录,第二个参数,创建时候的描述)

Created /app1

[zk: localhost:2181(CONNECTED) 4] create /app1/server101 “192.168.1.101”

Created /app1/server101

ls /

发现多了个刚才创建的两个目录

6)获得节点的值

[zk: localhost:2181(CONNECTED) 6] get /app1

hello app1

cZxid = 0x20000000a

ctime = Mon Jul 17 16:08:35 CST 2017

mZxid = 0x20000000a

mtime = Mon Jul 17 16:08:35 CST 2017

pZxid = 0x20000000b

cversion = 1

dataVersion = 0

aclVersion = 0

ephemeralOwner = 0x0

dataLength = 10

numChildren = 1

[zk: localhost:2181(CONNECTED) 8] get /app1/server101

192.168.1.101

cZxid = 0x20000000b

ctime = Mon Jul 17 16:11:04 CST 2017

mZxid = 0x20000000b

mtime = Mon Jul 17 16:11:04 CST 2017

pZxid = 0x20000000b

cversion = 0

dataVersion = 0

aclVersion = 0

ephemeralOwner = 0x0

dataLength = 13

numChildren = 0

7)创建短暂节点

[zk: localhost:2181(CONNECTED) 9] create -e /app-emphemeral 8888

(1)在当前客户端是能查看到的

[zk: localhost:2181(CONNECTED) 10] ls /

[app1, app-emphemeral, zookeeper]

(2)退出当前客户端然后再重启启动客户端

[zk: localhost:2181(CONNECTED) 12] quit

[atguigu@hadoop104 zookeeper-3.4.10]$ bin/zkCli.sh

(3)再次查看根目录下短暂节点已经删除

[zk: localhost:2181(CONNECTED) 0] ls /

[app1, zookeeper]

8)创建带序号的节点

(1)先创建一个普通的根节点app2

[zk: localhost:2181(CONNECTED) 11] create /app2 “app2”

(2)创建带序号的节点

[zk: localhost:2181(CONNECTED) 13] create -s /app2/aa 888

Created /app2/aa0000000000

[zk: localhost:2181(CONNECTED) 14] create -s /app2/bb 888

Created /app2/bb0000000001

[zk: localhost:2181(CONNECTED) 15] create -s /app2/cc 888

Created /app2/cc0000000002

如果原节点下有1个节点,则再排序时从1开始,以此类推。如果原来有两个就从2开始

[zk: localhost:2181(CONNECTED) 16] create -s /app1/aa 888

Created /app1/aa0000000001

9)修改节点数据值

[zk: localhost:2181(CONNECTED) 2] set /app1 999

通过get /app1 查看值是否别修改

10)节点的值变化监听

(1)在104主机上注册监听/app1节点数据变化

[zk: localhost:2181(CONNECTED) 26] get /app1 watch

(2)在103主机上修改/app1节点的数据

[zk: localhost:2181(CONNECTED) 5] set /app1 777

(3)观察104主机收到数据变化的监听

WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/app1

11)节点的子节点变化监听(路径变化)

(1)在104主机上注册监听/app1节点的子节点变化

[zk: localhost:2181(CONNECTED) 1] ls /app1 watch

[aa0000000001, server101]

或者get /app1 watch

(2)在103主机/app1节点上创建子节点

[zk: localhost:2181(CONNECTED) 6] create /app1/bb 666

Created /app1/bb

(3)观察104主机收到子节点变化的监听

WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/app1

意思就是别人修改了数据,我做出了监听,并且监听到了变化,数据发生了变化。

但是注意,这里的监听事件只能监听一次,即如果103再次修改这个目录,但是104监听不到了。

当然除了监听子节点的变化,也可以监听节点中数据的变化,即“”中的内容,即get /app1 得到的内容

12)删除节点(单一节点)

[zk: localhost:2181(CONNECTED) 4] delete /app1/bb

13)递归删除节点

[zk: localhost:2181(CONNECTED) 7] rmr /app2

14)查看节点状态

[zk: localhost:2181(CONNECTED) 12] stat /app1

cZxid = 0x20000000a

ctime = Mon Jul 17 16:08:35 CST 2017

mZxid = 0x200000018

mtime = Mon Jul 17 16:54:38 CST 2017

pZxid = 0x20000001c

cversion = 4

dataVersion = 2

aclVersion = 0

ephemeralOwner = 0x0

dataLength = 3

numChildren = 2

注意启动的时候通过jps,发现多了QuorumPeerMain不足以说明已经启动,必须通过bin/zkServersh status 查看时候有mode:leader或者mode:follower,才能说明已经正常启动。如果配置信息错误的话,前者是没问题的但是后面查看status是错误的

4.3 API应用

4.3.1 eclipse环境搭建

1)创建一个工程

2)解压zookeeper-3.4.10.tar.gz文件

3)拷贝zookeeper-3.4.10.jar、jline-0.9.94.jar、log4j-1.2.16.jar、netty-3.10.5.Final.jar、slf4j-api-1.6.1.jar、slf4j-log4j12-1.6.1.jar到工程的lib目录。并build一下,导入工程。

4)拷贝log4j.properties文件到项目根目录

4.3.2 创建ZooKeeper客户端:

//连接zookeeper的地址
private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
//会话超时时间单位毫秒
	private static int sessionTimeout = 2000;
	private ZooKeeper zkClient = null;

	@Before
	public void init() throws Exception {
//watcher监听事件
	zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
			@Override
			public void process(WatchedEvent event) {
				// 收到事件通知后的回调函数(用户的业务逻辑)
				System.out.println(event.getType() + "--" + event.getPath());

				// 再次启动监听
				//因为每次都会重新调用init方法
				//如果没有下面这几行的话,只能监听一次,就像之前介绍的linux指令一样
				try {
					zkClient.getChildren("/", true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

4.3.3 创建子节点

// 创建子节点
	@Test
	public void create() throws Exception {
		// 数据的增删改查
		// 参数1:要创建的节点的路径; 参数2:节点数据 ; 参数3:节点权限 ;参数4:节点的类型
		String nodeCreated = zkClient.create("/eclipse", "hello zk".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
	}

如果中断输出 None–null 然后输出/atguigu

这里的None–null是上面的System.out.println(event.getType() + “–” + event.getPath());监听输出的。

4.3.4 获取子节点

// 获取子节点
	@Test
	public void getChildren() throws Exception {
		List<String> children = zkClient.getChildren("/", true);

		for (String child : children) {
			System.out.println(child);
		}

		// 延时阻塞
		Thread.sleep(Long.MAX_VALUE);
	}

4.3.5 判断znode是否存在

// 判断znode是否存在
	@Test
	public void exist() throws Exception {
		Stat stat = zkClient.exists("/eclipse", false);

		System.out.println(stat == null ? "not exist" : "exist");
	}

4.3.6 监听服务器节点动态上下线案例

1)需求:某分布式系统中,主节点可以有多台,可以动态上下线,任意一台客户端都能实时感知到主节点服务器的上下线

2)需求分析



上图可以理解成淘宝双十一,第一步,服务端像zookeeper集群注册信息,就是去上面创建一个节点,servers是管理所有节点的最外层的信息,/severs/server1是路径,hadoop101 80 nodes是数据,hadoop101是代号,80nodes表示当前服务器连接了多少客户端,第二步,客户端获取刚才的信息,查看有几个server,根据拿到的数据,根据地址可以请求相应的服务器,第三步,服务器下线,下线之后zookeeper集群上的对应的节点信息就没了,第四部,下线的时间通知给客户端,第五步,重新获取服务器列表

3)具体实现:

(0)现在集群上创建/servers节点

[zk: localhost:2181(CONNECTED) 10] create /servers “servers”

Created /servers

(1)服务器端代码

package com.atguigu.zkcase;

import java.io.IOException;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;

public class DistributeServer {
	private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
	private static int sessionTimeout = 2000;
	private ZooKeeper zk = null;
	private String parentNode = "/servers";

	// 创建到zk的客户端连接
	//这里注意概念,不论是server,还是client对于zk来说都是client
	public void getConnect() throws IOException{

		zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {

			@Override
			public void process(WatchedEvent event) {
				// 收到事件通知后的回调函数(用户的业务逻辑)
				System.out.println(event.getType() + "--" + event.getPath());

				// 再次启动监听
				try {
					zk.getChildren("/", true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	// 注册服务器
	public void registServer(String hostname) throws Exception{
		String create = zk.create(parentNode + "/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

		System.out.println(hostname +" is noline "+ create);
	}

	// 业务功能
	public void business(String hostname) throws Exception{
		System.out.println(hostname+" is working ...");

		Thread.sleep(Long.MAX_VALUE);
	}

	public static void main(String[] args) throws Exception {
		// 获取zk连接
		DistributeServer server = new DistributeServer();
		server.getConnect();

		// 利用zk连接注册服务器信息
		server.registServer(args[0]);

		// 启动业务功能
		server.business(args[0]);
	}
}

(2)客户端代码

package com.atguigu.zkcase;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

public class DistributeClient {
	private static String connectString = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
	private static int sessionTimeout = 2000;
	private ZooKeeper zk = null;
	private String parentNode = "/servers";
	private volatile ArrayList<String> serversList = new ArrayList<>();

	// 创建到zk的客户端连接
	public void getConnect() throws IOException {
		zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {

			@Override
			public void process(WatchedEvent event) {
				System.out.print(event.getType()+"--"+event.getPath());
				// 再次启动监听
				try {
					//保证能循环监听。
					getServerList();

				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	//
	public void getServerList() throws Exception {

		// 获取服务器子节点信息,并且对父节点进行监听
		//true表示会执行上面的process这个监听的方法
		List<String> children = zk.getChildren(parentNode, true);
		ArrayList<String> servers = new ArrayList<>();
		//获取所有子节点信息
		for (String child : children) {
			byte[] data = zk.getData(parentNode + "/" + child, false, null);

			servers.add(new String(data));
		}

		// 把servers赋值给成员serverList,已提供给各业务线程使用
		serversList = servers;

		System.out.println(serversList);
	}

	// 业务功能
	public void business() throws Exception {
		System.out.println("client is working ...");
	}

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

		// 获取zk连接
		DistributeClient client = new DistributeClient();
		client.getConnect();

		// 获取servers的子节点信息,从中获取服务器信息列表
		client.getServerList();

		// 业务进程启动
		client.business();
	}
}







server端做相应的处理,客户端都能感知到。

大数据学习笔记之Zookeeper(四):Zookeeper实战篇(二)的更多相关文章

  1. 大数据学习系列之七 ----- Hadoop+Spark+Zookeeper+HBase+Hive集群搭建 图文详解

    引言 在之前的大数据学习系列中,搭建了Hadoop+Spark+HBase+Hive 环境以及一些测试.其实要说的话,我开始学习大数据的时候,搭建的就是集群,并不是单机模式和伪分布式.至于为什么先写单 ...

  2. 大数据学习笔记之Hadoop(一):Hadoop入门

    文章目录 大数据概论 一.大数据概念 二.大数据的特点 三.大数据能干啥? 四.大数据发展前景 五.企业数据部的业务流程分析 六.企业数据部的一般组织结构 Hadoop(入门) 一 从Hadoop框架 ...

  3. 大数据学习笔记——Java篇之集合框架(ArrayList)

    Java集合框架学习笔记 1. Java集合框架中各接口或子类的继承以及实现关系图: 2. 数组和集合类的区别整理: 数组: 1. 长度是固定的 2. 既可以存放基本数据类型又可以存放引用数据类型 3 ...

  4. 大数据学习笔记——Hadoop编程实战之HDFS

    HDFS基本API的应用(包含IDEA的基本设置) 在上一篇博客中,本人详细地整理了如何从0搭建一个HA模式下的分布式Hadoop平台,那么,在上一篇的基础上,我们终于可以进行编程实操了,同样,在编程 ...

  5. 大数据学习笔记——Linux完整部署篇(实操部分)

    Linux环境搭建完整操作流程(包含mysql的安装步骤) 从现在开始,就正式进入到大数据学习的前置工作了,即Linux的学习以及安装,作为运行大数据框架的基础环境,Linux操作系统的重要性自然不言 ...

  6. 大数据学习笔记之Hadoop(二):HDFS文件系统

    文章目录 一 HDFS概念 1.1 概念 1.2 组成 1.3 HDFS 文件块大小 二 HFDS命令行操作 三 HDFS客户端操作 3.1 eclipse环境准备 3.1.1 jar包准备 3.2 ...

  7. 大数据学习笔记——Linux基本知识及指令(理论部分)

    Linux学习笔记整理 上一篇博客中,我们详细地整理了如何从0部署一套Linux操作系统,那么这一篇就承接上篇文章,我们仔细地把Linux的一些基础知识以及常用指令(包括一小部分高级命令)做一个梳理, ...

  8. 大数据学习笔记——Java篇之IO

    IO学习笔记整理 1. File类 1.1 File对象的三种创建方式: File对象是一个抽象的概念,只有被创建出来之后,文件或文件夹才会真正存在 注意:File对象想要创建成功,它的目录必须存在! ...

  9. 大数据学习笔记之初识Hadoop

    1.Hadoop概述 1.1 Hadoop名字的由来 Hadoop项目作者的孩子给一个棕黄色的大象样子的填充玩具的命名 Hadoop的官网:http://hadoop.apache.org . 1.2 ...

随机推荐

  1. [19/05/07-星期二] JDBC(Java DataBase Connectivity)_CLOB(存储大量的文本数据)与BLOB(存储大量的二进制数据)

    一. CLOB(Character Large Object ) – 用于存储大量的文本数据 – 大字段有些特殊,不同数据库处理的方式不一样,大字段的操作常常是以流的方式来处理的.而非一般的字段,一次 ...

  2. Java-集合第五篇Map集合

    1.什么是Map集合. Map用于保存具有映射关系的数据.key和value都可以是任意引用类型,但key不允许重复,即同一个Map的任何两个key通过equals方法比较总是返回false. 从Ja ...

  3. stl(set或map)

    https://nanti.jisuanke.com/t/41384 There are nnn points in an array with index from 111 to nnn, and ...

  4. AcWing 831. KMP字符串(模板)

    给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字. 模板串P在模式串S中多次作为子串出现. 求出模板串P在模式串S中所有出现的位置的起始下标. 输入格式 第一行输入整 ...

  5. osi七层协议 Open System Interconnection

    一, 操作系统基础 操作系统:(Operating System,简称OS)是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在"裸机"上的最基本的系统软件,任何其他软件都必 ...

  6. spring aop实现数据库的读写分离

    为了减轻数据库的压力,一般会使用数据库主从(master/slave)的方式,但是这种方式会给应用程序带来一定的麻烦,比如说,应用程序如何做到把数据写到master库,而读取数据的时候,从slave库 ...

  7. Codeforces - 6E - Exposition - 尺取

    https://codeforc.es/problemset/problem/6/E 既然可以多个log,那就直接map伺候.尺取之后要查询区间里面的最大值和最小值的差.众所周知尺取的时候要是不是有序 ...

  8. python学习第四十九天XML模块的用法

    xml是实现不通语言或程序之间进行数据交换的协议,跟json差不多,但是json用起来简单,还没诞生json,以前都是用xml,下面讲述XML模块的用法. 1,导入xml模块 import xml 2 ...

  9. Python 函数知识总汇

    函数在一个程序起到很重要的作用,那么如何学好函数呢,那函数有什么内容的,总结一下函数的知识归类 1,函数定义 def  函数名(): print("...") 2,函数返回值 re ...

  10. NIO的缓冲区、通道、选择器关系理解

    Buffer的数据存取    一个用于特定基本数据类行的容器.有java.nio包定义的,所有缓冲区都是抽象类Buffer的子类.   Java NIO中的Buffer主要用于与NIO通道进行交互,数 ...