(一)zookeeper单机模式的安装和使用

1、分布式常见问题

  • 容易出现死锁
  • 容易活锁,处于活锁的线程都是非阻塞的,而且每个线程都抢不到资源,会造成cpu的耗费
  • 集群的管理问题,比如某台的宕机需要能够检测到
  • 集群配置文件的统一管理问题
  • 集群中信息更新通知问题,某一台机器发布一个信息,能够让整个集群的机器都知道
  • 管理集群的选举问题,管理集群的机器本身也是一个集群(例如zookeeper集群),其中有一台为主(选举得到),其他为从。
  • 分布式锁

2、Zookeeper定义

Zookeeper是一个分布式的协调服务框架,Zookeeper可以解决分布式环境常见的问题:统一命名服务,信息配置管理,数据一致性,集群管理,分布式锁等等。

3、Zookeeper的安装

  • 下载压缩包:链接:https://pan.baidu.com/s/1NtffnJ0ttT475KSQqAKcSw  提取码:0qp5
  • 解压:tar -xf zookeeper-3.4.7.tar.gz
  • 创建配置文件:zookeeper的配置文件是conf/zoo.cfg,conf目录下有一个配置文件的样本zoo_sample.cfg,复制该文件并修改文件名为zoo.cfg即可
  • 更改配置文件内容:单机模式配置如下,其中dataDir为存储快照的目录,建议修改为自定义目录
# 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=/opt/zookeeper/tmp
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# 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
#autopurge.purgeInterval=1

4、zookeeper的数据结构

Zookeeper存储数据的结构是一棵树,如图所示:

(一)zookeeper单机模式的安装和使用_第1张图片

Zookeeper数据结构的特征:

  • 有一个根节点 /,对于Zookeeper的操作都要基于根节点
  • 每个节点都叫做Znode节点,都可以创建自己的子节点,都可以存储数据
  • 整个Znode树会存储在内存中,提高查询速度。为了防止数据丢失,同时也会把Znode树落到磁盘上,磁盘路径即配置文件zoo.cfg里dataDir指定的目录
  • Znode的路径是全局唯一的
  • 创建节点时,需指定初始化数据,否则创建报错
  • Zookeeper是事务的概念,针对每个事务(创建,更新或删除节点等),Zookeeper都会分配一个递增的Zxid(事务id)。其中有cZxid(创建节点的事务id),mZxid(修改节点的事务id)

5、Zookeeper单机模式启动,查看,关闭

  • 进入bin目录,启动zookeeper:sh  zkServer.sh  start
  • 验证是否启动:jps命令查看活动的java进程

(一)zookeeper单机模式的安装和使用_第2张图片

  • 查看状态:sh  zkServer.sh  status

  • 停止服务:sh zkServer.sh stop

6、Zookeeper客户端启动及操作

小技巧:在客户端中,使用命令:ctrl + l 清屏。

  • 进入bin目录,启动客户端:sh zkCli.sh
  • 查询节点 ls /     ls /zookeeper

(一)zookeeper单机模式的安装和使用_第3张图片

  • 创建节点:create /node01 hello

创建了节点 node01,并初始化数据为 “hello” 

  • 查看节点:get /node01

可以看出,当执行命令  create /node01 hello时,这就是一个写的事务,会分配一个事务id,事务id是一个自增的id。

(一)zookeeper单机模式的安装和使用_第4张图片

  • 修改节点数据:set /node01 hellodfr
  • 删除节点:delete /node01 单个删除,存在子节点则删除失败    rmr /node01 递归删除,

7、zookeeper的节点类型

  • create /park01 "dateStr" 普通持久节点
  • create -e /park01 "dateStr" 普通临时节点
  • create -s /park01 "dateStr" 顺序持久节点 
  • create -e -s /park01 "dateStr" 临时顺序节点 
临时节点

客户端连接zookeeper服务并创建临时节点后,若客户端掉线,则临时节点会消失。

该特性可以用来检测集群中,有哪些机器挂掉

顺序节点

创建顺序节点后,会在节点名称后带上一个自增的顺序id

如创建节点 create -s /park01 ddff,真正创建的节点名称为 park010000000009

8、通过代码操作zookeeper

  • 下载Zookeeper相关jar包:链接:https://pan.baidu.com/s/1ZlEBsshFOr_us44JpMGUpA  提取码:5v0x
  • 创建Maven的java工程,pom.xml配置如下

  4.0.0
  com.dfr
  zookeeper
  0.0.1-SNAPSHOT
  
  
  	 
         junit
         junit
         4.10     
      
     
   	 
         org.slf4j
         slf4j-simple
         1.6.4
         compile
      
      
     
	 	 org.apache.zookeeper
		 zookeeper
	 	 3.4.7
	 
		
  
  
  
  
  • jar包简单了解:工程创建成功后,可以看到依赖的jar包

netty是一个网络通信的框架,底层是基于NIO来写的,zookeeper就是通过netty来与其他机器进行网络交互的。

(一)zookeeper单机模式的安装和使用_第5张图片

  • Zookeeper的连接,和基本操作
package com.dfr.zookeeper;

import java.util.List;
import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.junit.Test;

public class TestDemo {
	@Test
	public void testConnect() throws Exception {
		
		
		//连接操作是异步的(非阻塞连接),如果不做任何处理,可能导致还没连接成功,testConnect方法线程就已经关闭了。
		//这里使用递减锁来处理
		final CountDownLatch cdl = new CountDownLatch(1);
		
		//ip端口,连接超时时间,监听者
		ZooKeeper zk = new ZooKeeper("39.107.244.148:2181", 3000, new Watcher() {

			@Override
			public void process(WatchedEvent event) {
				if(event.getState() == KeeperState.SyncConnected) {
					System.out.println("连接成功!");
					cdl.countDown();
				} 
			}
			
		});
		//递减锁没减到0则阻塞
		cdl.await();
		
		//创建节点
		//参数:节点,存储数据,权限,节点类型
		zk.create("/gtt", "MsGao".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
		
		//修改节点数据
		//参数:节点,存储数据,数据版本号
		//每更新一次,dataVersion + 1
		zk.setData("/gtt", "gttTWO".getBytes(), 0);
		
		//如果不需要确认当前数据版本,则传入版本号为-1
		zk.setData("/gtt", "gtt0000".getBytes(), -1);
		
		//删除数据
		//版本号传-1,则直接删除节点
		zk.delete("/gtt", -1);
		
		//获取数据
		//参数:节点,监听者,节点的状态信息如时间戳等
		byte[] byteDate = zk.getData("/dfr", null, null);
		System.out.println(new String(byteDate));
		
		//获取子节点
		//参数:节点,监听者
		List list = zk.getChildren("/", null);
		
		for(String str : list) {
			System.out.println(str);
		}
		
		
	}
}
  • 对节点进行事件监听

事件类型

(一)zookeeper单机模式的安装和使用_第6张图片

代码示例如下,注意zookeeper中监听默认是一次性的。要想永久监听需要自己处理。

package com.dfr.zookeeper;

import java.util.concurrent.CountDownLatch;

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

public class TestDemo2 {
	@Test
	public void test() throws Exception {
		
		
		//连接操作是异步的(非阻塞连接),如果不做任何处理,可能导致还没连接成功,testConnect方法线程就已经关闭了。
		//这里使用递减锁来处理
		final CountDownLatch cdl = new CountDownLatch(1);
		
		//ip端口,连接超时时间,监听者
		ZooKeeper zk = new ZooKeeper("39.107.244.148:2181", 3000, new Watcher() {

			@Override
			public void process(WatchedEvent event) {
				if(event.getState() == KeeperState.SyncConnected) {
					System.out.println("连接成功!");
					cdl.countDown();
				} 
			}
			
		});
		
		//对节点进行事件监听,此处以getData方法为例,可以自行选择监听事件类型
		
		//zk的默认监听机制是:一次性监听
		/*zk.getData("/dfr", new Watcher() {
			
			@Override
			public void process(WatchedEvent event) {
				if(event.getType() == EventType.NodeDataChanged) {
					System.out.println("节点数据改变了!");
				}
			}
		}, null);
		
		while(true);
		*/
		
		//永久监听
		//监听事件的类型从EventType中选择
		for(;;) {
			final CountDownLatch countdl = new CountDownLatch(1);
			
			zk.getData("/dfr", new Watcher() {
				
				@Override
				public void process(WatchedEvent event) {
					if(event.getType() == EventType.NodeDeleted) {
						System.out.println("节点数据删除了!");
						countdl.countDown();
					}
				}
			}, null);
			
			countdl.await();
		}
		
	}
}

 

你可能感兴趣的:(zookeeper)