Zookeeper入门

一、ZooKeeper 是什么

ZooKeeper是一种开源的为分布式应用所设计的协作服务,用于维护配置信息,命名,提供分布式同步和提供组服务。所有这些类型的服务都以分布式应用程序的某种形式使用。Zookeeper由java语言编写,支持Java和C两种编程语言。

二、ZooKeeper 提供了什么?

zookeeper提供了文件系统以及通知机制。

三、Zookeeper 文件系统

Zookeeper维护一个类似于文件系统的数据结构:

与文件系统相同的是其命名空间由斜线分隔开的路径名序列所组成,每一个节点都通过路径识别;

与文件系统不同的是每个节点中可以携带数据(包括数据,数据长度,创建时间,修改时间等),即每一个节点既可以当作文件夹来看,也可以当作文件来看。

 

通知机制

       客户端注册监听他关心的目录节点,当节点目录发生变化时,zookeeper会通知客户端。


四、znode

Zookeeper的节点称为Znode,znode的特点如下:

1.每个节点都可以存储数据(kb级别),以及存储状态信息(时间戳,顺序号,ACL,版本号),可进行的操作(增删改查)。当节点的数据发生变化,其版本号将增加;

2.znode具原子性,其读写分离。读操作时读取所有znode数据,写操作将修改所有的数据;

3.每一个节点都具有ACL(Access Control List 访问控制列表),其规定用户对节点的操作权限。

znode的类型:

java源码在CreateMode枚举类中提供一下四种类型:

    /**
     * The znode will not be automatically deleted upon client's disconnect.  
     */
    PERSISTENT (0, false, false),
    /**
    * The znode will not be automatically deleted upon client's disconnect,
    * and its name will be appended with a monotonically increasing number.
    */
    PERSISTENT_SEQUENTIAL (2, false, true),
    /**
     * The znode will be deleted upon the client's disconnect.
     */
    EPHEMERAL (1, true, false),
    /**
     * The znode will be deleted upon the client's disconnect, and its name
     * will be appended with a monotonically increasing number.
     */
    EPHEMERAL_SEQUENTIAL (3, true, true);

1. PERSISTENT:永久节点,即使客户端连接断开,节点依旧存在,使用delete才能删除,默认创建的是该类型的节点;

2. PERSISTENT_SEQUENTIAL:其具备PERSISTENT节点的特点,同时在创建时,它的路径末尾会附加一个单调递增的计数器;

3. EPHEMERAL:临时节点,客户端断开,临时节点就会失效,该节点下不能有子节点;

4. EPHEMERAL_SEQUENTIAL:其具备EPHEMERAL节点的特点,同时在创建时,它的路径末尾会附加一个单调递增的计数器;

拓展:

1. 临时节点

Zookeeper的客户端和服务器端通信采用的是长连接的方式,每个客户端和服务器端的通信通过保持心跳来连接,这个连接状态称为session。只要创建znode的会话处于活动状态,就会存在这些znode。客户端session失效,对应的临时节点便会失效,znode将被删除。由于这种行为,短暂的znodes不允许有子节点。由此可见,临时节点的生命周期是由session决定的。

一个临时znode,在以下两种情况下将会被删除:
1.当创建该znode的客户端的会话因超时或主动关闭而中止时。
2.当某个客户端(不一定是创建者)主动删除该节点时。

 

2.序列节点 - 唯一命名

创建序列节点时,ZooKeeper在节点路径末尾附加一个单调递增的计数器。此计数器对于父znode是唯一的。计数器的格式为%010d - 即10位数字,0(零)填充(计数器以这种方式格式化以简化排序)。注意:用于存储下一个序列号的计数器是由父节点维护的signed int(4字节),当递增超过2147483647时计数器将溢出(导致名称 ”-2147483648" )。

如下图: 我创建一个/aa的序列节点,zookeeper会自动在后面添加一个十位数的序列号。

 

五、Zookeeper安装(单机模式)

在zookeeper官网上下载安装包,我下载的是zookeeper-3.5.0-alpha.tar.gz,下载完成之后,使用Xftp或其他工具将文件上传到服务器,然后使用Xshell进行操作。

5.1 首先解压安装包

tar -zxvf zookeeper-3.5.0-alpha.tar.gz

5.2 解压后切换(cd)到conf目录下,然后在该目录下创建一个zoo_sample.cfg文件

tickTime=2000     ZooKeeper使用的基本时间单位(以毫秒为单位)。它用于做心跳,最小会话超时将是tickTime的两倍

dataDir=/usr/zk35/data     文件路径根据自己的进行修改   数据文件

clientPort=2181    客户端端口

5.3 创建好配置文件后,可以开始启动ZooKeeper:

bin/zkServer.sh start

bin/zkServer.sh start-foreground  启动前台

bin/zkServer.sh status 查看状态

5.4 可使用下列语句停止服务

bin/zkServer.sh stop

5.5 启动客户端,连接到Zookeeper

bin/zkCli.sh 

5.6 连接成功后,会出现下面的内容

Connecting to localhost:2181
此处省略
watcher=org.apache.zookeeper.ZooKeeperMain$MyWatcher@22927a81
Welcome to ZooKeeper!
2019-07-18 09:10:30,690 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1093] - Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)
JLine support is enabled
2019-07-18 09:10:30,854 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@963] - Socket connection established to localhost/127.0.0.1:2181, initiating session
2019-07-18 09:10:30,905 [myid:] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1346] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x16c02a0f0950000, negotiated timeout = 30000

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
[zk: localhost:2181(CONNECTED) 0] 

5.7 连接成功后,便可以在客户端进行操作了;

六、Zookeeper的简单操作

可使用help指令查看命令及其所需参数

[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
	addauth scheme auth
	close 
	config [-c] [-w] [-s]
	connect host:port
	create [-s] [-e] path [data] [acl]
	delete [-v version] path
	deleteall path
	delquota [-n|-b] path
	get [-s] [-w] path
	getAcl [-s] path
	history 
	listquota path
	ls [-s] [-w] path
	ls2 path [watch]
	printwatches on|off
	quit 
	reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
	redo cmdno
	removewatches path [-c|-d|-a] [-l]
	rmr path
	set [-s] [-v version] path data
	setAcl [-s] [-v version] path acl
	setquota -n|-b val path
	stat [-w] path
	sync path

1. 创建Znode

语法:create /path /data     ex: create /FirstZnode hello   (3.5版本及以后)   默认创建的是持久的

创建顺序节点:create -s /path /data     保证Znode路径唯一  

创建临时节点:create -e /path /data     前面已经说过,当会话过期或者是客户端连接断开后临时节点将被自动删除。

2.获取数据

语法:get /path      ex: get /FirstZnode          如果访问顺序节点,必须输入完整路径:get /FirstZnode000000001

3.监视Znode

只能在get命令中设置

语法:get /path -w     ex get  /FirstZnode  -w         开启监视后,可使用set对该znode进行修改,Server端会产生信息。

4.设置数据

语法: set /path /data

完成后,可使用get CLI命令检查数据

5.创建znode的子节点

语法:create /parent_path/subnode_path /data       ex  create /FirstZnode/subnode hello 

6.查看znode下的子节点

语法:ls /path

7.检查状态

状态描述指定znode的元数据,包含时间戳,版本号,ACL,数据长度和子node等细项。

语法:stat /path   

8.移除/删除znode

语法:rmr/delete/deleteall /path

区别:rmr/deleteall /path 可用于移除指定的znode并递归删除其下所有子节点

           delete /path  只适用于没有子节点的znode

七、Java实现

在使用Zookeeper服务之前,我们必须先创建Zookeeper的实例(就像当时连接数据库一样,需要写一个JDBC工具类)。在org.apache.zookeeper中包含了Zookeeper类,我们在进行客户端操作时,会经常使用该类。如果Zookeeper和客户端建立连接,Zookeeper就会分配给该连接会话一个id值,并且客户端会顶起发送心跳给服务器来维持会话的连接。在该连接的基础上,我们就可以通过连接Zookeeper的客户端来调用API进行操作。

1.  ZookeeperConnection类,用于连接Zookeeper

package com.yc.zktest1;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;

public class ZookeeperConnection {

	private static ZooKeeper zk;
	final CountDownLatch connectSignal = new CountDownLatch(1);

	public ZooKeeper connect(String host) throws IOException, InterruptedException {

		zk = new ZooKeeper(host, 5000, new Watcher() {
			// 回调方法 //event :事件
			public void process(WatchedEvent event) {
				System.out.println("事件发生了,详情如下:");
				System.out.println(event.getType());
				System.out.println(event.getState());
				System.out.println(event.getPath());
				if (event.getState() == KeeperState.SyncConnected) {
					System.out.println("客户机与zk连接成功。。。。");
					connectSignal.countDown();
					System.out.println("递减后的值" + connectSignal.getCount());
				}
			}

		});
		connectSignal.await();
		System.out.println("主程序创建zk对象成功");
		return zk;

	}

	public static void main(String[] args) throws IOException, InterruptedException {
		ZookeeperConnection zc = new ZookeeperConnection();
		ZooKeeper zk = zc.connect("192.168.176.132");
		System.out.println(zk);
		zc.close();
	}

	private void close() throws InterruptedException {
		zk.close();
	}

}

2.ZookeeperUtil类 用于实现Zookeeper客户端的操作

public class ZookeeperUtil1 {

	private static ZooKeeper zk;
	private static ZookeeperConnection zc = new ZookeeperConnection();

	//静态块  程序一加载到jvm就执行
	static {
		try {
			zk = zc.connect("192.168.176.132");
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 创建节点
	 * @param path
	 * @param data
	 * @throws KeeperException
	 * @throws InterruptedException
	 */
	public static void create(String path, byte[] data) throws KeeperException, InterruptedException {
		zk.create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
	}
	
	/**
	 * Return the data and the stat of the node of the given path.
	 * get
	 */
	public static void get(String path, boolean watch) throws KeeperException, InterruptedException {
		Stat stat = zk.exists(path, false);
		byte[] data = zk.getData(path,false, stat );
		String v = new String(data,0,data.length);
		System.out.println("节点   "+path+"  的值是  "+v);
	}
	
	/**
	 * set
	 */
	public static void set( String path,String content , int version) throws KeeperException, InterruptedException {
		byte[] data = content.getBytes();
		zk.setData(path, data,-1);
	}
	
	/**
	 * getAcl
	 * Return the ACL and stat of the node of the given path.
	 */
	public static void getAcl( String path) throws KeeperException, InterruptedException {
		Stat stat = zk.exists(path, false);
		List<ACL> acl = zk.getACL(path, stat );
		System.out.println(acl);
	}
	
	public static void setAcl(String path, int version) throws KeeperException, InterruptedException {
		zk.setACL(path,ZooDefs.Ids.OPEN_ACL_UNSAFE, version);
	}
	
	/**
	 * 递归删除节点    等效于Zookeeper里面的rmr deleteall 
	 * @param path
	 * @param version  = cversion
	 * if the given version is -1, it matches any node's versions
	 * @throws InterruptedException
	 * @throws KeeperException
	 */
	public static void rmr(String path,int version) throws InterruptedException, KeeperException {
		zk.delete(path, version);
	}
	
	/**
	 * Return the stat of the node of the given path
	 * whether need to watch this node
	 * @param path
	 * @throws InterruptedException 
	 * @throws KeeperException 
	 */
	public static void stat(String path) throws KeeperException, InterruptedException{
		Stat s = zk.exists(path, false);
		System.out.println("==============stat===========");
		System.out.println(s);
	}
	
	public static void getChildren(String path, boolean watch) throws KeeperException, InterruptedException{
		List<String> children = zk.getChildren(path, false);
		System.out.println(path + " 的子节点有 "+ children);
	}
}

八、Curator

官网飞机票:https://curator.apache.org/getting-started.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Zookeeper是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理数据,并且能够通知已注册的观察者响应数据状态的变化。如果你想了解如何入门使用Zookeeper,可以按照以下步骤进行操作: 1. 首先,确保你已经安装了Zookeeper并正确配置了环境变量。 2. 接下来,你可以查看Zookeeper的日志文件,它默认保存在启动zkServer命令所在的目录中的zookeeper.out文件中。你也可以通过修改bin/zkEnv.sh文件中的ZOO_LOG_DIR变量来指定日志文件保存的位置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Zookeeper入门](https://blog.csdn.net/weixin_44079636/article/details/118580234)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Zookeeper 入门](https://blog.csdn.net/weixin_45417821/article/details/118383129)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Zookeeper入门学习](https://blog.csdn.net/weixin_44261754/article/details/130118788)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值