1.Zookeeper上的数据操作
上一篇中我们介绍了zk是什么,以及zk的工作流程。既然zk是协调服务的,那必然会存储一些节点的信息,比附说Hadoop高可用集群HA的活跃NameNode信息,活跃ResourceManager信息(后面会介绍配置HA),Kafka的消息对了等等一些分布式节点信息,那这些基本信息是存储在zk哪里的,以及格式是什么样子?
启动zk的客户端与服务器
$>bin/zkServer.sh start
$>zkCli.sh -server s10:2181 //进入zk命令行
我们在客户端使用help来查看一下帮助,看看zk有哪些命令
$zk]help //查看帮助
我们看到有一个create命令,这个就是用来创建数据的,根据提供的格式,我们可以看到格式是create path data,说明了zk在创建数据的时候是创建了一个目录,目录上有数据啊,这点特别重要,这就是zk上的数据格式。zk上存放的数据格式是:目录 数据。也就是创建的每一个目录都有值,我们试着创建一下:
我们看到最后一个创建的目录是 /a/a1,但在创建之前目录/a必须存在,只能先创建父节点,再创建子节点,并且每次在创建的时候必须给予值,否则不会创建成功。创建完成之后我们ls /查看一下
不给值,创建不成功
看到都是一层层的目录
使用 get 目录 来获得这个目录的值
注意:在get命令获得这个目录的数据之后,我们会发现有一个特别重要的属性:dataVersion:数据的版本(自增,没修改一次加1)。zk使用这个属性来控制并发,在进行修改数据的时候,只有修改数据操作的版本号与其一致,zk才允许其进行修改,例如同时有两个线程A,B同时修改目录/a的数据,版本号就会对其进行控制,假设A先修改数据,数据版本经查看后一致,允许修改,并且同时版本号加1,B再修改的时候就会发现版本号不一致(因为A,B在同一版本号操作,A的操作导致版本号加1),则不会允许进行操作。
使用 set 目录 数据 修改这个目录的值
我们看到create命令,后面有两个可选择的命令,分别是[s],[e]分别代表什么意思呢,[s]-序列目录,[e]-临时目录
zk中的3种目录类型
-----------------
1.持久目录(默认,不加[e],[s])
client结束,还存在。
2.临时目录
在client活动时有效,断开自动删除。临时目录不能有子目录。
leader推选是使用。
3.序列目录
在目录名之后附加10个数字,主要用于同步和锁.
那zk上的数据都保存在哪里了呢?在我们上一篇搭建单机版zk的zoo.cfg目录中配置的
version-2文件夹里面有数据文件,只不过对数据进行了一些操作(比如加密,编译等类似操作)。
这个目录就是zk用来存储协同分布式服务时的一些数据,并且数据格式是目录。
2.使用JAVA API来访问Zookeeper
(pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.it18zhang</groupId>
<artifactId>ZooKeeperDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>
</project>
(java文件)
package com.hadoop.zktest;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
import org.junit.Test;
import java.util.List;
/**
*
*/
public class TestZK {
//显示所有根目录
@Test
public void ls() throws Exception{
ZooKeeper zk = new ZooKeeper("s10:2181",5000,null);
List<String> list = zk.getChildren("/",null);
for(String s : list){
System.out.println(s);
}
}
//显示所有目录
@Test
public void lsAll() throws Exception{
ls("/");
}
/**
* 列出指定path下的孩子
*/
public void ls(String path) throws Exception{
System.out.println(path);
ZooKeeper zk = new ZooKeeper("s10:2181",5000,null);
List<String> list = zk.getChildren(path,null);
if(list == null || list.isEmpty()){
return ;
}
for(String s : list){
//先输出孩子
if(path.equals("/")){
ls(path + s);
}
else{
ls(path + "/" + s);
}
}
}
/**
* 设置数据
*/
@Test
public void setData() throws Exception{
ZooKeeper zk = new ZooKeeper("s10:2181", 5000, null);
zk.setData("/a","tomaslee".getBytes(),0);
}
/**
* 创建临时节点
*/
@Test
public void reateEmphoral() throws Exception{
ZooKeeper zk = new ZooKeeper("s10:2181", 5000, null);
zk.create( "/c/c1" ,"tom".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("hello");
}
//观察者模式(zk提供观察者模式来在数据更改时用来感知变化,也供leader的选择)
//观察。
// client能够通过watch机制在数据发生变化时收到通知。
// client可以在read 节点时设置观察者。watch机制会发送通知给注册的客户端。
//观察模式只触发一次。
// session过期,watch机制删除了。
@Test
public void testWatch() throws Exception{
final ZooKeeper zk = new ZooKeeper("s10:2181", 5000, null);
Stat st = new Stat();
Watcher w = null ;
w = new Watcher() {
//回调
public void process(WatchedEvent event) {
try {
System.out.println("数据改了!!!");
zk.getData("/a", this, null);
} catch (Exception e) {
e.printStackTrace();
}
}
};
byte[] data = zk.getData("/a", w , st);
System.out.println(new String(data));
while(true){
Thread.sleep(1000);
}
}
}
leader推选过程(最小号选举法)
-------------------
1.所有节点在同一目录下创建临时序列节点。
2.节点下会生成/xxx/xx000000001等节点。
3.序号最小的节点就是leader,其余就是follower.
4.每个节点观察小于自己节点的主机。(注册观察者)
5.如果leader挂了,对应znode删除了。
6.观察者收到通知。
7.序号最小的节点就是leader
更加具体的博文
来源:https://blog.csdn.net/u011444062/article/details/81075873