鉴于前面几篇博客已经将zookeeper单机和集群搭建完成,现在我们来了解下如何使用代码操作zookeeper
本文是建立连接和数据存储
直接开始干货:
首先pom文件引入zookeeper依赖,我装的版本是3.6.0 大家根据情况来定。
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.0</version>
</dependency>
码来~~~~
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
/**
* @Title: Spring-distributed
* @Description:
* @author: liaryank
* @Date: 2020/5/6 11:28 上午
* @Version: 1.0
*/
public class ZookeeperClient {
public static void main(String[] args) {
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
//这里绑定zookeeper服务器除了 observe 都要写上 因为可能出现任何一台机器成为leader 4000是心跳
ZooKeeper zooKeeper = new ZooKeeper("192.168.3.32:2181," +
"192.168.3.33:2181,192.168.3.34:2181", 4000, new Watcher() {
// watcher 的概念建议请看下面
@Override
public void process(WatchedEvent watchedEvent) {
if (Event.KeeperState.SyncConnected== watchedEvent.getState()){
//如果收到了服务端的响应事件,连接成功
countDownLatch.countDown();
}
}
});
countDownLatch.await();
System.out.println(zooKeeper.getState());
//添加节点 ACL:ZooDefs.Ids.OPEN_ACL_UNSAFE权限控制 open是任何人都可以访问,PERSISTENT节点类型为持久化
zooKeeper.create("/zk-persis-liaryank","0".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
Thread.sleep(1000);
Stat stat=new Stat();
//得到当前节点的值 stat是当前节点的值 也就是自己创建的/zk-persis-liaryank的值
byte[] bytes=zooKeeper.getData("/zk-persis-liaryank",null,stat);
System.out.println(new String(bytes));
//修改节点值 Version这里是属于乐观锁
zooKeeper.setData("/zk-persis-liaryank","1".getBytes(),stat.getVersion());
//得到当前节点的值
byte[] bytes1=zooKeeper.getData("/zk-persis-liaryank",null,stat);
System.out.println(new String(bytes1));
//zooKeeper.delete("/zk-persis-liaryank",stat.getVersion());
zooKeeper.close();
if (zooKeeper != null) {
System.out.println("关闭连接");
zooKeeper.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException | KeeperException e) {
e.printStackTrace();
}
}
}
运行结果
服务器端查看 stat就是下面图中的数据,都可以获取到,可以自行打印输出下
已经将0 改为了1
再试试删除
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
/**
* @Title: Spring-distributed
* @Description:
* @author: liaryank
* @Date: 2020/5/6 11:28 上午
* @Version: 1.0
*/
public class ZookeeperClient {
public static void main(String[] args) {
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
ZooKeeper zooKeeper = new ZooKeeper("192.168.3.32:2181," +
"192.168.3.33:2181,192.168.3.34:2181", 4000, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
if (Event.KeeperState.SyncConnected== watchedEvent.getState()){
//如果收到了服务端的响应事件,连接成功
countDownLatch.countDown();
}
}
});
countDownLatch.await();
System.out.println(zooKeeper.getState());
Stat stat=new Stat();
//得到当前节点的值
byte[] bytes=zooKeeper.getData("/zk-persis-liaryank",null,stat);
zooKeeper.delete("/zk-persis-liaryank",stat.getVersion());
zooKeeper.close();
if (zooKeeper != null) {
System.out.println("关闭连接");
zooKeeper.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException | KeeperException e) {
e.printStackTrace();
}
}
运行结果
你可以将删除直接写到上边一起执行一下 加点打印输出就可以看到完整的增删改查效果了。
ok现在我们来讲事件机制
讲事件机制前先补充一下watcher
Watcher 监听机制是 Zookeeper 中非常重要的特性,我们 基于 zookeeper 上创建的节点,可以对这些节点绑定监听 事件,比如可以监听节点数据变更、节点删除、子节点状 态变更等事件,通过这个事件机制,可以基于 zookeeper 实现分布式锁、集群管理等功能.
watcher 特性:当数据发生变化的时候, zookeeper 会产 生一个 watcher 事件,并且会发送到客户端。但是客户端 只会收到一次通知。如果后续这个节点再次发生变化,那 么之前设置 watcher 的客户端不会再次收到消息。 (watcher 是一次性的操作)。 可以通过循环监听去达到 永久监听效果.
注册事件机制: 通过这三个操作来绑定事件 :getData、Exists、getChildren
触发事件: 凡是事务类型的操作,都会触发监听事件。 create /delete /setData
watcher 事件类型
None (-1), 客户端链接状态发生变化的时候,会收到 none 的事件
NodeCreated (1), 创建节点的事件。 比如zk-persis-liaryank时
NodeDeleted (2), 删除节点事件。
NodeDataChanged (3), 节点数据发生变更时。
NodeChildrenChanged (4); 子节点被创建、被删除、会 发生事件触发
码来~~~
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
/**
* @Title: Spring-distributed
* @Description:
* @author: liaryank
* @Date: 2020/5/6 3:19 下午
* @Version: 1.0
*/
public class WatcherDemo {
public static void main(String[] args) {
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
ZooKeeper zooKeeper = new ZooKeeper("192.168.3.32:2181," +
"192.168.3.33:2181,192.168.3.34:2181", 4000, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("全局默认事件:"+watchedEvent.getType());
if (Event.KeeperState.SyncConnected== watchedEvent.getState()){
//如果收到了服务端的响应事件,连接成功
countDownLatch.countDown();
}
}
});
countDownLatch.await();
System.out.println(zooKeeper.getState());
zooKeeper.create("/zk-persis-liaryank","1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
//这里通过exits绑定事件
Stat stat = zooKeeper.exists("/zk-persis-liaryank", new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println(watchedEvent.getType()+"==>"+watchedEvent.getPath());
try {
//再一次绑定事件,相当于永久注册监听 这里设置的true 是全局的watch
zooKeeper.exists(watchedEvent.getPath(),true);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
//修改事务类型的操作来出发监听事件
stat=zooKeeper.setData("/zk-persis-liaryank","2".getBytes(),stat.getVersion());
Thread.sleep(1000);
//然后删除
zooKeeper.delete("/zk-persis-liaryank",stat.getVersion());
//修改的时候让该内容进入只读状态
System.in.read();
zooKeeper.close();
if (zooKeeper != null) {
System.out.println("关闭连接");
zooKeeper.close();
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException | KeeperException e) {
e.printStackTrace();
}
}
}
运行结果如下
ok 原生操作到这里就完事了