Zookeeper基础(一)分布式协调工具

目录

zookeeper 应用场景

 zookeeper 数据结构--树状

Zookeeper windows环境安装

Zookeeper客户端

Zookeeper集群环境搭建(linux)

结构

修改zookeeper环境变量

修改zoo_sample.cfg文件

创建服务器标识

复制zookeeper

常用命令

Zookeeper配置文件介绍

Java操作Zookeeper

Zookeeper说明

Maven依赖信息

Zookeeper客户端连接

创建Zookeeper节点信息

Watcher

什么是Watcher接口

Watcher代码


zookeeper 应用场景

zookeeper分布式开源框架,解决分布式工具

应用场景: dubbo rpc远程调用框架 +zookeeper注册中心 (命名服务)

zookeeper 1发布订阅--watcher 对zk节点发生改变,都会有事件通知。

                  2负载均衡--所有服务注册到zookeeper

                  3分布式通知--所有服务注册到zookeeper后,节点改变,用watcher通知

                  4mater选举策略--主备 投票机制 用ping机制 心跳机制检测进行选举

                  5分布式锁 全局锁--redis  zookeeper  springcloud

                  6分布式配置中心

                  7大数据

                  8分布式队列--一般不用

使用zookeeper实现原理--面

 zookeeper 数据结构--树状

 zookeeper 数据结构 xml --树状存储结构 节点名称不能重复

 

            

Zookeeper windows环境安装

环境要求:必须要有jdk环境,本次讲课使用jdk1.8

1.安装jdk

2.安装Zookeeper. 在官网http://zookeeper.apache.org/下载zookeeper.我下载的是zookeeper-3.4.6版本。

解压zookeeper-3.4.6至D:\machine\zookeeper-3.4.6.

在D:\machine 新建data及log目录。

3.ZooKeeper的安装模式分为三种,分别为:单机模式(stand-alone)、集群模式和集群伪分布模式。ZooKeeper 单机模式的安装相对比较简单,如果第一次接触ZooKeeper的话,建议安装ZooKeeper单机模式或者集群伪分布模式。

安装单击模式。 至D:\machine\zookeeper-3.4.6\conf 复制 zoo_sample.cfg 并粘贴到当前目录下,命名zoo.cfg.

执行 如果打不开jar  

用命令 java -jar xxx.jar 执行

 

Zookeeper客户端

ZooKeeper命令行工具类似于Linux的shell环境,不过功能肯定不及shell啦,但是使用它我们可以简单的对ZooKeeper进行访问,数据创建,数据修改等操作.  使用 zkCli.sh -server 127.0.0.1:2181 连接到 ZooKeeper 服务,连接成功后,系统会输出 ZooKeeper 的相关环境以及配置信息。

命令行工具的一些简单操作如下:

1. 显示根目录下、文件: ls / 使用 ls 命令来查看当前 ZooKeeper 中所包含的内容

2. 显示根目录下、文件: ls2 / 查看当前节点数据并能看到更新次数等数据

3. 创建文件,并设置初始内容: create /zk "test" 创建一个新的 znode节点“ zk ”以及与它关联的字符串

4. 获取文件内容: get /zk 确认 znode 是否包含我们所创建的字符串

5. 修改文件内容: set /zk "zkbak" 对 zk 所关联的字符串进行设置

6. 删除文件: delete /zk 将刚才创建的 znode 删除

7. 退出客户端: quit

8. 帮助命令: help

Zookeeper集群环境搭建(linux)

环境要求:必须要有jdk环境,本次讲课使用jdk1.8

结构

一共三个节点
(zk服务器集群规模不小于3个节点),要求服务器之间系统时间保持一致。

上传zk并且解压进行解压: tar -zxvf zookeeper-3.4.6.tar.gz
重命名: mv zookeeper-3.4.6 zookeeper

修改zookeeper环境变量

vi /etc/profile

export JAVA_HOME=/opt/jdk1.8.0_71

export ZOOKEEPER_HOME=/usr/local/zookeeper

export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

export PATH=$JAVA_HOME/bin:$ZOOKEEPER_HOME/bin:$PATH

 

source /etc/profile

修改zoo_sample.cfg文件


cd /usr/local/zookeeper/conf
mv zoo_sample.cfg zoo.cfg

修改conf: vi zoo.cfg 修改两处
(1) dataDir=/usr/local/zookeeper/data(注意同时在zookeeper创建data目录)
(2)最后面添加
server.0=bhz:2888:3888
server.1=hadoop1:2888:3888
server.2=hadoop2:2888:3888

创建服务器标识
 

服务器标识配置:
创建文件夹: mkdir data
创建文件myid并填写内容为0: vi
myid (内容为服务器标识 : 0)

复制zookeeper

进行复制zookeeper目录到hadoop01和hadoop02
还有/etc/profile文件
把hadoop01、 hadoop02中的myid文件里的值修改为1和2
路径(vi /usr/local/zookeeper/data/myid)

启动zookeeper
启动zookeeper:
路径: /usr/local/zookeeper/bin
执行: zkServer.sh start
(注意这里3台机器都要进行启动)
状态: zkServer.sh
status(在三个节点上检验zk的mode,一个leader和俩个follower)

常用命令

zkServer.sh status 查询状态

 

Zookeeper配置文件介绍

# The number of milliseconds of each tick 

tickTime=2000 

 

# The number of ticks that the initial  

# synchronization phase can take 

initLimit=10 

 

# The number of ticks that can pass between  

# sending a request and getting an acknowledgement 

syncLimit=5 

 

# the directory where the snapshot is stored. 

# do not use /tmp for storage, /tmp here is just  

# example sakes. 

dataDir=/home/myuser/zooA/data 

 

# the port at which the clients will connect 

clientPort=2181 

 

# ZooKeeper server and its port no. # ZooKeeper ensemble should know about every other machine in the ensemble # specify server id by creating 'myid' file in the dataDir # use hostname instead of IP address for convenient maintenance

server.1=127.0.0.1:2888:3888 

server.2=127.0.0.1:2988:3988  

server.3=127.0.0.1:2088:3088 

 

# Be sure to read the maintenance section of the  

# administrator guide before turning on autopurge. 

# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance 

# The number of snapshots to retain in dataDir 

# autopurge.snapRetainCount=3 

# Purge task interval in hours 

# Set to "0" to disable auto purge feature  <br>

#autopurge.purgeInterval=1 

dataLogDir=/home/myuser/zooA/log

 

 

tickTime:心跳时间,为了确保连接存在的,以毫秒为单位,最小超时时间为两个心跳时间

initLimit:多少个心跳时间内,允许其他server连接并初始化数据,如果ZooKeeper管理的数据较大,则应相应增大这个值

clientPort:服务的监听端口

dataDir:用于存放内存数据库快照的文件夹,同时用于集群的myid文件也存在这个文件夹里(注意:一个配置文件只能包含一个dataDir字样,即使它被注释掉了。)

dataLogDir:用于单独设置transaction log的目录,transaction log分离可以避免和普通log还有快照的竞争

syncLimit:多少个tickTime内,允许follower同步,如果follower落后太多,则会被丢弃。

 

server.A=B:C:D:
A是一个数字,表示这个是第几号服务器,B是这个服务器的ip地址
C第一个端口用来集群成员的信息交换,表示的是这个服务器与集群中的Leader服务器交换信息的端口
D是在leader挂掉时专门用来进行选举leader所用

Java操作Zookeeper

Zookeeper说明

创建节点(znode) 方法:
create:
提供了两套创建节点的方法,同步和异步创建节点方式。

同步方式:
参数1,节点路径《名称) : InodeName (不允许递归创建节点,也就是说在父节点不存在
的情况下,不允许创建子节点)
参数2,节点内容: 要求类型是字节数组(也就是说,不支持序列化方式,如果需要实现序
列化,可使用java相关序列化框架,如Hessian、Kryo框架)
参數3,节点权限: 使用Ids.OPEN_ACL_UNSAFE开放权限即可。(这个参数一般在权展
没有太高要求的场景下,没必要关注)
参数4,节点类型: 创建节点的类型: CreateMode,提供四种首点象型

PERSISTENT                    持久化节点

PERSISTENT_SEQUENTIAL        顺序自动编号持久化节点,这种节点会根据当前已存在的节点数自动加 1

EPHEMERAL                     临时节点, 客户端session超时这类节点就会被自动删除

EPHEMERAL_SEQUENTIAL         临时自动编号节点

Maven依赖信息

<dependency>
			<groupId>org.apache.zookeeper</groupId>
			<artifactId>zookeeper</artifactId>
			<version>3.4.6</version>
		</dependency>

Zookeeper客户端连接

public class Test001 {

	//连接地址
	private static final String ADDRES = "127.0.0.1:2181";
	//session 会话 超时时间
	private static final int SESSION_OUTTIME = 2000;
	//信号量,阻塞程序执行,用户等待zookeeper连接成功,发送成功信号,
	private static final CountDownLatch countDownLatch = new CountDownLatch(1);

	public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
    
		ZooKeeper zk = new ZooKeeper(ADDRES, SESSION_OUTTIME, new Watcher() {
     //事件通知 子线程
			public void process(WatchedEvent event) {
				// 获取事件状态
				KeeperState keeperState = event.getState();
				// 获取事件类型
				EventType eventType = event.getType();
				if (KeeperState.SyncConnected == keeperState) {
					if (EventType.None == eventType) {
						countDownLatch.countDown();
						System.out.println("zk 启动连接...");
					}

				}
			}
		});
		// 进行阻塞
		countDownLatch.await();
            //主线程
		String result = zk.create("/itmayeidu_Lasting", "Lasting".getBytes(), Ids.OPEN_ACL_UNSAFE,
				CreateMode.PERSISTENT);
		System.out.println(result);
		zk.close();
	}

}

创建Zookeeper节点信息


1.	创建持久节点,并且允许任何服务器可以操作
	String result = zk.create("/itmayiedu_Lasting", "Lasting".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
	System.out.println("result:" + result);
2.	创建临时节点
	String result = zk.create("/itmayiedu_temp", "temp".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
	System.out.println("result:" + result);

Watcher

在ZooKeeper中,接口类Watcher用于表示一个标准的事件处理器,其定义了事件通知相关的逻辑,包含KeeperState和EventType两个枚举类,分别代表了通知状态和事件类型,同时定义了事件的回调方法:process(WatchedEvent event)

什么是Watcher接口

同一个事件类型在不同的通知状态中代表的含义有所不同,表7-3列举了常见的通知状态和事件类型。

表7-3 Watcher通知状态与事件类型一览

 

KeeperState

EventType

触发条件

说明

 

None
(-1)

客户端与服务端成功建立连接

 

SyncConnected
(0)

NodeCreated
(1)

Watcher监听的对应数据节点被创建

 

 

NodeDeleted
(2)

Watcher监听的对应数据节点被删除

此时客户端和服务器处于连接状态

 

NodeDataChanged
(3)

Watcher监听的对应数据节点的数据内容发生变更

 

 

NodeChildChanged
(4)

Wather监听的对应数据节点的子节点列表发生变更

 

Disconnected
(0)

None
(-1)

客户端与ZooKeeper服务器断开连接

此时客户端和服务器处于断开连接状态

Expired
(-112)

Node
(-1)

会话超时

此时客户端会话失效,通常同时也会受到SessionExpiredException异常

AuthFailed
(4)

None
(-1)

通常有两种情况,1:使用错误的schema进行权限检查 2:SASL权限检查失败

通常同时也会收到AuthFailedException异常

表7-3中列举了ZooKeeper中最常见的几个通知状态和事件类型。

回调方法process()

process方法是Watcher接口中的一个回调方法,当ZooKeeper向客户端发送一个Watcher事件通知时,客户端就会对相应的process方法进行回调,从而实现对事件的处理。process方法的定义如下:

abstract public void process(WatchedEvent event);

这个回调方法的定义非常简单,我们重点看下方法的参数定义:WatchedEvent。

WatchedEvent包含了每一个事件的三个基本属性:通知状态(keeperState),事件类型(EventType)和节点路径(path),其数据结构如图7-5所示。ZooKeeper使用WatchedEvent对象来封装服务端事件并传递给Watcher,从而方便回调方法process对服务端事件进行处理。

提到WatchedEvent,不得不讲下WatcherEvent实体。笼统地讲,两者表示的是同一个事物,都是对一个服务端事件的封装。不同的是,WatchedEvent是一个逻辑事件,用于服务端和客户端程序执行过程中所需的逻辑对象,而WatcherEvent因为实现了序列化接口,因此可以用于网络传输。

服务端在生成WatchedEvent事件之后,会调用getWrapper方法将自己包装成一个可序列化的WatcherEvent事件,以便通过网络传输到客户端。客户端在接收到服务端的这个事件对象后,首先会将WatcherEvent还原成一个WatchedEvent事件,并传递给process方法处理,回调方法process根据入参就能够解析出完整的服务端事件了。

需要注意的一点是,无论是WatchedEvent还是WatcherEvent,其对ZooKeeper服务端事件的封装都是机及其简单的。举个例子来说,当/zk-book这个节点的数据发生变更时,服务端会发送给客户端一个“ZNode数据内容变更”事件,客户端只能够接收到如下信

Watcher代码

public class ZkClientWatcher implements Watcher {
	// 集群连接地址
	private static final String CONNECT_ADDRES = "192.168.110.159:2181,192.168.110.160:2181,192.168.110.162:2181";
	// 会话超时时间
	private static final int SESSIONTIME = 2000;
	// 信号量,让zk在连接之前等待,连接成功后才能往下走.
	private static final CountDownLatch countDownLatch = new CountDownLatch(1);
	private static String LOG_MAIN = "【main】 ";
	private ZooKeeper zk;
          //zk创建连接
	public void createConnection(String connectAddres, int sessionTimeOut) {
		try {
			zk = new ZooKeeper(connectAddres, sessionTimeOut, this);
			System.out.println(LOG_MAIN + "zk 开始启动连接服务器....");
			countDownLatch.await();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
            //创建持久化节点
	public boolean createPath(String path, String data) {
		try {
			this.exists(path, true);
			this.zk.create(path, data.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
			System.out.println(LOG_MAIN + "节点创建成功, Path:" + path + ",data:" + data);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 判断指定节点是否存在
	 * 
	 * @param path
	 *            节点路径
	 */
	public Stat exists(String path, boolean needWatch) {
		try {
			return this.zk.exists(path, needWatch);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public boolean updateNode(String path,String data) throws KeeperException, InterruptedException {
		exists(path, true);
		this.zk.setData(path, data.getBytes(), -1);
		return false;
	}

	public void process(WatchedEvent watchedEvent) {

		// 获取事件状态
		KeeperState keeperState = watchedEvent.getState();
		// 获取事件类型
		EventType eventType = watchedEvent.getType();
		// zk 路径
		String path = watchedEvent.getPath();
		System.out.println("进入到 process() keeperState:" + keeperState + ", eventType:" + eventType + ", path:" + path);
		// 判断是否建立连接
		if (KeeperState.SyncConnected == keeperState) {
			if (EventType.None == eventType) {
				// 如果建立建立成功,让后程序往下走
				System.out.println(LOG_MAIN + "zk 建立连接成功!");
				countDownLatch.countDown();
			} else if (EventType.NodeCreated == eventType) {
				System.out.println(LOG_MAIN + "事件通知,新增node节点" + path);
			} else if (EventType.NodeDataChanged == eventType) {
				System.out.println(LOG_MAIN + "事件通知,当前node节点" + path + "被修改....");
			}
			else if (EventType.NodeDeleted == eventType) {
				System.out.println(LOG_MAIN + "事件通知,当前node节点" + path + "被删除....");
			}

		}
		System.out.println("--------------------------------------------------------");
	}

	public static void main(String[] args) throws KeeperException, InterruptedException {
		ZkClientWatcher zkClientWatcher = new ZkClientWatcher();
		zkClientWatcher.createConnection(CONNECT_ADDRES, SESSIONTIME);
//		boolean createResult = zkClientWatcher.createPath("/p15", "pa-644064");
		zkClientWatcher.updateNode("/pa2","7894561");
	}

}

 

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值