您的位置:首页 > 编程语言

分布式协调服务zookeeper02-zookeeper核心工作机制以及api代码演示

2017-11-03 10:54 851 查看
一.Zookeeper命令行操作

1. 客户端连接:运行 zkCli.sh –server <ip>进入命令行工具

2.查看znode路径:ls /mygirls

3. 获取znode数据:get /mygirls

4. 监听znode事件:

      ls /mygirls  watch     ## 就对一个节点的子节点变化事件注册了监听

     get /mygirls watch     ## 就对一个节点的数据内容变化事件注册了监听

   注意: 监听器只生效一次

     监听器的工作机制,其实是在客户端会专门创建一个监听线程,在本机的一个端口上等待zk集群发送过来事件

二.Zookeeper核心工作机制

1. zookeeper特性

1/Zookeeper:一个leader,多个follower组成的集群

2/全局数据一致:每个server保存一份相同的数据副本,client无论连接到哪个server,数据都是一致的

3/分布式读写,更新请求转发,由leader实施

4/更新请求顺序进行,来自同一个client的更新请求按其发送顺序依次执行

5/数据更新原子性,一次数据更新要么成功(半数以上节点成功),要么失败

6/实时性,在一定时间范围内,client能读到最新数据

2.zookeeper数据结构

1/层次化的目录结构,命名符合常规文件系统规范(见下图)

2/每个节点在zookeeper中叫做znode,并且其有一个唯一的路径标识

3/节点Znode可以包含数据(只能存储很小量的数据,<1M;最好是1k字节以内)和子节点(但是EPHEMERAL类型的节点不能有子节点)



3. 节点类型

1/Znode有两种类型:

短暂(ephemeral)(断开连接自己删除)

持久(persistent)(断开连接不删除)

2/Znode有四种形式的目录节点(默认是persistent


PERSISTENT

PERSISTENT_SEQUENTIAL(持久序列/test0000000019


EPHEMERAL

EPHEMERAL_SEQUENTIAL

3/创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护

4/在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序

客户端应用可以在节点上设置监视器

三.Zookeeper 客户端API

 1. 基本使用

org.apache.zookeeper.Zookeeper是客户端入口主类,负责建立与server的会话

它提供以下几类主要方法  :

功能
描述
create

在本地目录树中创建一个节点

delete

删除一个节点

exists

测试本地是否存在目标节点

get/set data

从目标节点上读取 / 写数据

get/set ACL

获取 / 设置目标节点访问控制列表信息

get children

检索一个子节点上的列表

sync

等待要被传送的数据

2. api代码演示

 public class SimpleZkClient {

private static final String connectString = "mini1:2181,mini2:2181,mini3:2181";

 private static final int sessionTimeout = 2000;

// latch就相当于一个对象锁,当latch.await()方法执行时,方法所在的线程会等待

// 当latch的count减为0时,将会唤醒等待的线程

CountDownLatch latch = new CountDownLatch(1);

ZooKeeper zkClient = null;

@Before

public void init() throws Exception {

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

// 事件监听回调方法

@Override

public void process(WatchedEvent event) {

if (latch.getCount() > 0 && event.getState() == KeeperState.SyncConnected) {

System.out.println("countdown");

latch.countDown();

}

// 收到事件通知后的回调函数(应该是我们自己的事件处理逻辑)

System.out.println(event.getType() + "---" + event.getPath());

System.out.println(event.getState());

}

});

latch.await();

/*

 * States state = zkClient.getState(); while(state!=States.CONNECTED){

 * Thread.sleep(1000); }

 */

}

/**

 * 数据的增删改查

 *

 * @throws InterruptedException

 * @throws KeeperException

 */

// 创建数据节点到zk中

@Test

public void testCreate() throws KeeperException, InterruptedException {

// 参数1:要创建的节点的路径 参数2:节点大数据 参数3:节点的权限
参数4:节点的类型

String nodeCreated = zkClient.create("/eclipse", "hellozk".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

// 上传的数据可以是任何类型,但都要转成byte[]

zkClient.close();

}

// 判断znode是否存在

@Test

public void testExist() throws Exception {

Stat stat = zkClient.exists("/eclipse", false);

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

}

// 获取子节点

@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);

}

// 获取znode的数据

@Test

public void getData() throws Exception {

byte[] data = zkClient.getData("/eclipse", true, null);

System.out.println(new String(data));

Thread.sleep(Long.MAX_VALUE);

}

// 删除znode

@Test

public void deleteZnode() throws Exception {

 

// 参数2:指定要删除的版本,-1表示删除所有版本

zkClient.delete("/eclipse", -1);

}

// 删除znode

@Test

public void setData() throws Exception {

zkClient.setData("/app1", "imissyou angelababy".getBytes(), -1);

byte[] data = zkClient.getData("/app1", false, null);

System.out.println(new String(data));

}

}

 

public class TestZKclient {

static ZooKeeper zk = null;

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

final CountDownLatch countDownLatch = new CountDownLatch(1);

zk = new ZooKeeper("mini1:2181", 2000, new Watcher() {

@Override

public void process(WatchedEvent event) {

if (event.getState() == KeeperState.SyncConnected) {

countDownLatch.countDown();

}

System.out.println(event.getPath());

System.out.println(event.getType());

try {

zk.getChildren("/myboys", true);

} catch (Exception e) {

e.printStackTrace();

}

}

});

countDownLatch.await();

/*

 * zk.create("/myboys", "丑陋型".getBytes("UTF-8"), Ids.OPEN_ACL_UNSAFE,

 * CreateMode.PERSISTENT); zk.close();

 */

 

/*

 * byte[] data = zk.getData("/myboys", true, null);

 * System.out.println(new String(data,"UTF-8"));

 *

 * Thread.sleep(Long.MAX_VALUE);

 */

/*List<String> children = zk.getChildren("/myboys", true);

for (String child : children) {

            System.out.println(child);

}*/

/*zk.delete("/myboys/wangkai", -1);*/

/*zk.setData("/myboys","sldakfjsd".getBytes(),-1);*/

Stat stat = zk.exists("/mywives", true);

System.out.println(stat==null?"确实不存在":"存在");

zk.close();

}

}

 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  api