一、节点的原生api操作
1.使用Java代码操作zookeeper,首先需要导入Zookeeper的依赖;
2.需要跟运行zookeeper服务的虚拟机创建会话,检查连接状态,用来查看是否断开或者连接不上;最后是Zookeeper节点的一些增删改查操作。
3.java代码:
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
//1.创建会话
/**
* 第一个参数:zookeeper服务地址
* 第二个参数:会话超时时间
* 第三个参数:监听机制
*/
ZooKeeper zk = new ZooKeeper("192.168.126.4:2181,192.168.126.5:2181,192.168.126.6:2181", 4000, null);
//查看连接状态
System.out.println(zk.getState());
/**
* 创建节点
* 第一个参数:节点名
* 第二个参数:节点数据
* 第三个参数: ACL策略
* 第四个参数: 节点类型 (持久PERSISTENT 临时EPHEMERAL 持久序号 临时序号)
*/
// zk.create("/node1","1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// System.out.println("========== 创建节点成功 ============");
//判断节点是否存在
// Stat exists = zk.exists("/node2", null);
// System.out.println(exists.toString());
//删除节点
// zk.delete("/node1",-1);
//修改节点
// zk.setData("/node1","zzx".getBytes(),-1);
//获取节点数据
// byte[] data = zk.getData("/node1", null, null);
// System.out.println(new String(data));
//获取节点(非数据)
List<String> children = zk.getChildren("/node1", null);
for (String child:children) {
System.out.println(child);
}
}
二、监听机制的原生api操作
1.创建一个Zookeeper实例,对getChildren监听,即对包括该节点同其所有子节点进行监听,当子节点发生删除或添加,才能触发机制,对于操作数据则不触发。
2.对getData监听,即监听该节点的数据,当该节点的数据发生变化时,触发机制
3.java代码
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ZooKeeper zk = new ZooKeeper("192.168.126.4:2181,192.168.126.5:2181,192.168.126.6:2181", 4000, null);
//注册监听机制 监听节点
zk.getChildren("/node1", new Watcher() {
//监听回调
@Override
public void process(WatchedEvent watchedEvent) {
//监听路径
System.out.println(watchedEvent.getPath());
//监听类型
System.out.println(watchedEvent.getType());
System.out.println("节点被修改了");
}
});
//监听节点数据
zk.getData("/root", new Watcher() {
//监听回调
@Override
public void process(WatchedEvent watchedEvent) {
//监听路径
System.out.println(watchedEvent.getPath());
//监听类型
System.out.println(watchedEvent.getType());
System.out.println("节点数据被修改了");
}
},null);
//使用线程休眠,防止程序运行结束退出,或者使用线程启动
Thread.sleep(Long.MAX_VALUE);
}
三、使用zkclient操作Zookeeper
zkclient是Github上的一个开源Zookeeper客户端,在Zookeeper原生API接口上进行了包装,是一个更加容易使用的Zookeeper客户端。同时Zkclient在内部实现了诸如Session超时重连,Watcher反复注册等功能,从而提高开发效率。
1.需要导入zkclient依赖
2.实现zkClient操作Zookeeper原生api的调用,节点数据的增删改查,还有节点的监听和节点数据的监听机制。
3.问题:此时在节点数据监听时,在linux命令行执行set /node2 abc进行修改时,此时不触发数据修改事件,然而使用zkClient的writeData方法时才能触发。
4.java代码
public static void main(String[] args) throws InterruptedException {
//1.创建会话
ZkClient zkClient = new ZkClient("192.168.126.4:2181,192.168.126.5:2181,192.168.126.6:2181");
//2.获取子节点
// List children = zkClient.getChildren("/node1");
// children.forEach(f->{
// System.out.println(f);
// });
//3.创建节点
// zkClient.create("/node2","2", CreateMode.PERSISTENT);
// System.out.println("创建节点成功");
//4.修改节点数据
// zkClient.writeData("/node2","zzx");
//5.获取节点数据
// Object o = zkClient.readData("/node2");
// System.out.println(o);
//6.删除数据
// zkClient.delete("/node2");
//7.注册节点监听事件
zkClient.subscribeChildChanges("/node1", new IZkChildListener() {
@Override
public void handleChildChange(String s, List<String> list) throws Exception {
System.out.println("数据改变");
list.forEach(f->{
System.out.println(f);
});
}
});
//8.注册数据监听事件
zkClient.subscribeDataChanges("/node2", new IZkDataListener() {
@Override
public void handleDataDeleted(String s) throws Exception {
System.out.println("数据被删除了");
System.out.println(s);
}
@Override
public void handleDataChange(String s, Object o) throws Exception {
System.out.println("数据改变了");
System.out.println(s);
System.out.println(o);
}
});
//防止程序运行结束后退出
Thread.sleep(Long.MAX_VALUE);
}
四、Curator操作Zookeeper
curator-framework:对zookeeper的底层api的一些封装。
curator-client:提供一些客户端的操作,例如重试策略等。
curator-recipes:封装了一些高级特性,如:Cache事件监听,选举,分布式锁,分布式计数器,分布式Barrier等。
1.添加curator依赖
2.问题,当注入5.2.1最新版时,出现如下错误
当注入4.2.0版本则没有问题。
3.curator解决了反复注册监听的问题,也有对节点的增删改查
4.java代码:
public static void main(String[] args) throws Exception {
//1.创建会话
String connStr = "192.168.126.4:2181,192.168.126.5:2181,192.168.126.6:2181";
CuratorFramework cur = CuratorFrameworkFactory
.builder()
.connectString(connStr)
.connectionTimeoutMs(5000)
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
.build();
//连接
cur.start();
//2.创建节点
// cur.create().withMode(CreateMode.PERSISTENT).forPath("/node3","3".getBytes());
//3.获取节点数据
// byte[] data = cur.getData().forPath("/node3");
// System.out.println(new String(data));
//4.删除一个节点
// cur.delete().forPath("/node3");
//5.删除节点并且这个节点里面有子节点(递归删除)
// cur.delete().deletingChildrenIfNeeded().forPath("/node3");
//6.修改节点数据
// cur.setData().forPath("/node3","aaa".getBytes());
//7.获取节点的所有子节点
// List strings = cur.getChildren().forPath("/node3");
// strings.forEach(f->{
// System.out.println(f);
// });
//8.监听机制
NodeCache nodeCache = new NodeCache(cur, "/node3");
nodeCache.getListenable().addListener(()->{
System.out.println("被修改了");
});
nodeCache.start();
Thread.sleep(Long.MAX_VALUE);
}
五、Zookeeper的高级特性
1.四字命令,即4个字母组成的命令
conf,cons,stat,ruok,mntr
需要在zoo.cfg配置文件中配置,vim zoof.cfg
;添加:4lw.commands.whitelist=*
配置完后,需要重启zookeeper:zkstart.sh restart
安装netcat(nc):yum install nc -y
conf,输出zookeeper服务的详细配置信息:echo conf | nc localhost 2181
cons,输出当前这台服务器上所有客户端连接的详细信息,包括每个客户端的客户端IP、会话ID和最后一次与服务器交互的操作类型等:echo cons | nc localhost 2181
ruok,输出当前ZooKeeper服务器是否正在运行。如果当前ZooKeeper服务器正在运行,那么返回“imok”,否则没有任何响应输出:echo ruok | nc localhost 2181
stat,用于获取ZooKeeper服务器的运行状态信息,包括基本的ZooKeeper版本、打包信息、运行时角色、集群数据节点个数等信息,另外还会将当前服务器的客户端连接信息打印出来:echo stat | nc localhost 2181
mnrt,列出集群的关键性能数据,包括zk的版本、最大/平均/最小延迟数、数据包接收、发送量、连接数、zk角色、node数量、watch数量、临时节点数:echo mnrt | nc localhost 2181
2.选举机制
选举机制原则:
zookeeper采用半数机制的选举方法;
zookeeper集群中只有半数以上的服务器启动,才能正常工作;
在集群正常工作之前,myid小的服务器给myid大的服务器投票,直到选出Leader,集群正常工作。
选举机制中的概念:
serverid:服务器id
编号越大在选择算法中的权重越大
zxid:数据ID
值越大说明数据越新,在选举算法中数据越新权重越大
Epoch:逻辑时钟
或叫投票次数,同一轮投票过程中的逻辑时钟值时相同的。每投完一次票这个数据就会增加,然后与接收到的其它服务器返回的投票信息中的数值相比,根据不同的值做出不同的判断。
Zookeeper服务器的数量最好设置为奇数。
假死:由于心跳超时(网络原因导致的)认为Leader死了,但其实leader还存活着;
脑裂:由于假死会发起新的Leader选举,选举出一个新的Leader,但旧的Leader网络又通了,导致出现了两个Leader ,有的客户端连接到老的Leader,而有的客户端则连接到新的leader。
总结:
1.有原生api操作zookeeper节点及数据;在此基础上,出现了zkClient封装原生api,操作zookeeper节点更加简易;curator采用Cache事件监听解决了原生api需要反复注册监听的问题,提供重试策略等。
2.zookeeper的节点操作,说到底就是节点的增删改查;采用了半数机制的选举方法;Zookeeper服务器的数量最好设置为奇数。
3.四字命令,conf,cons,ruok,stat,mnrt,常用的是conf,cons,stat;而ruok有时当服务器没有运行也会打印imok,不太靠谱。可以采用stat