Zookeeper作用?
Zookeeper是一个高效的分布式协调服务,可以提供配置信息管理、命名、分布式同步、集群管理、数据库切换等服务。它不适合用来存储大量信息,可以用来存储一些配置、发布与订阅等少量信息。
Zookeeper中的进程:
Zookeeper集群中的节点,根据其身份特性分为leader、follower、observer。
leader负责客户端writer类型的请求;
follower负责客户端reader类型的请求,并参与leader选举;
observer是特殊的follower,可以接收客户端reader请求,但是不会参与选举,可以用来扩容系统支撑能力,提高读取速度
安装
-
上传Zookeeper安装包至 /usr/local/soft/ 目录中
-
解压安装包
tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz mv apache-zookeeper-3.5.7-bin zookeeper-3.5.7
-
修改配置文件
mv zoo_sample.cfg zoo.cfg # 修改zoo.cfg dataDir=/usr/local/soft/zookeeper-3.5.7/data server.0=master:2888:3888 server.1=node1:2888:3888 server.2=node2:2888:3888
-
创建data目录
mkdir /usr/local/soft/zookeeper-3.5.7/data
-
在data目录中添加myid并且根据配置文件中的server添加对于的编号
-
分发目录到其他节点
cd /usr/local/soft/zookeeper-3.5.7
scp -r zookeeper-3.5.7/ node2:/usr/local/soft/
scp -r zookeeper-3.5.7/ node1:/usr/local/soft/
-
修改node1和node2中myid的编号
-
修改环境变量并使其生效
# ZOOKEEPER_HOME export ZOOKEEPER_HOME=/usr/local/soft/zookeeper-3.5.7 export PATH=$PATH:$ZOOKEEPER_HOME/bin source /etc/profile
-
三个节点上启动zookeeper
zkServer.sh start zkServer.sh status
-
客户端连接ZK命令
zkCli.sh 表示连接默认ip及端口号 localhost:2181 zkCli.sh -server node1:2181 表示连接指定IP及端口号
Zookeeper命令
查看路径下的节点 ls path
创建节点
create 节点 --> 创建普通节点
create 节点 节点数据 --> 创建普通节点并携带数据
create -s 节点 --> 创建节点并在节点名称后添加编号
create -e 节点 --> 创建临时节点
获取节点中的数据
get 节点
get -s 节点 查看节点中的数据并获取详细状态信息
get -w 节点 表示监听某个节点中的变化(只会触发一次效果)
设置节点中的数据
set 节点 数据 --> 给节点重新赋予数据 获取节点状态信息
stat 节点
删除节点
delete 节点 -- 可以删除一个不为空的节点(没有子节点)
deleteall 节点 退出客户端 quit
ZookeeperAPI使用
1、创建连接
public class Code01ZookeeperCon {
public static void main(String[] args) throws IOException, InterruptedException {
/**
* public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher)
*/
ZooKeeper zooKeeper = new ZooKeeper("master:2181,node1:2181,node2:2181"
, 10 * 1000
, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("Zookeeper连接发送变动..正在执行Process函数");
}
}
);
/**
* Watcher类中的Process函数是一个异步调用的函数,并且在整个执行过程中,
* 如果有连接发送变动,那么就会被触发一次
*/
System.out.println("连接成功...");
zooKeeper.close(3 * 1000);
}
}
2、创建永久节点
public class Code02ZookeeperCreate {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
/**
* public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher)
*/
ZooKeeper zooKeeper = new ZooKeeper("master:2181,node1:2181,node2:2181"
, 10 * 1000
, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("Zookeeper连接发送变动..正在执行Process函数");
}
}
);
/**
* public String create(final String path, byte data[], List<ACL> acl,
* CreateMode createMode)
*
* ZooDefs.Ids类中对应有枚举数据:
* OPEN_ACL_UNSAFE 创建的节点具有读写全部的权限
* CREATOR_ALL_ACL 表示有写的权限
* READ_ACL_UNSAFE 表示有读的权限
*
* CreateMode为枚举类型,可以设定创建节点的类型
* PERSISTENT 普通节点,持久化节点
* PERSISTENT_SEQUENTIAL 普通序列化节点
* EPHEMERAL 临时节点
*/
String res = zooKeeper.create("/api"
, "api_data".getBytes()
, ZooDefs.Ids.OPEN_ACL_UNSAFE
, CreateMode.PERSISTENT
);
System.out.println(res);
zooKeeper.close(3 * 1000);
}
}
3、创建临时节点
public class Code02ZookeeperCreateEphemeral {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
/**
* public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher)
*/
ZooKeeper zooKeeper = new ZooKeeper("master:2181,node1:2181,node2:2181"
, 10 * 1000
, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("Zookeeper连接发送变动..正在执行Process函数");
}
}
);
/**
* public String create(final String path, byte data[], List<ACL> acl,
* CreateMode createMode)
*
* ZooDefs.Ids类中对应有枚举数据:
* OPEN_ACL_UNSAFE 创建的节点具有读写全部的权限
* CREATOR_ALL_ACL 表示有写的权限
* READ_ACL_UNSAFE 表示有读的权限
*
* CreateMode为枚举类型,可以设定创建节点的类型
* PERSISTENT 普通节点,持久化节点
* PERSISTENT_SEQUENTIAL 普通序列化节点
* EPHEMERAL 临时节点
*/
/**
* 临时节点会在连接关闭后自动清除
*
*/
String res = zooKeeper.create("/api_EPHEMERAL"
, "api_data".getBytes()
, ZooDefs.Ids.OPEN_ACL_UNSAFE
, CreateMode.EPHEMERAL
);
System.out.println(res);
Thread.sleep(100 * 1000);
zooKeeper.close(3 * 1000);
}
}
4、获取节点数据
public class Code03GetData {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ZooKeeper zooKeeper = new ZooKeeper("master:2181,node1:2181,node2:2181"
, 10 * 1000
, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("Zookeeper连接发送变动..正在执行Process函数");
}
}
);
String path = "/api";
Stat exists = zooKeeper.exists(path, false);
if (exists != null){
byte[] data = zooKeeper.getData(path, false, exists);
String dataRes = new String(data);
System.out.println(dataRes);
}else {
System.out.println("节点不存在...");
}
zooKeeper.close(3*1000);
}
}
5、获取当前路径下的节点
public class Code04GetChildren {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ZooKeeper zooKeeper = new ZooKeeper("master:2181,node1:2181,node2:2181"
, 10 * 1000
, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("Zookeeper连接发送变动..正在执行Process函数");
}
}
);
String path = "/api";
Stat exists = zooKeeper.exists(path, false);
System.out.println(exists.getNumChildren());
// 当传入的path没有子节点时,整个程序会直接报错,所以需要在获取子节点之前对当前路径进行判断
if(exists.getNumChildren() > 0){
List<String> children = zooKeeper.getChildren(path, false);
for (String child : children) {
System.out.println(child);
}
}
zooKeeper.close(3*1000);
/**
* 作业:
* 要求获取path路径下的所有子节点
*/
}
}
6、
public class Code05GetDataWatcher {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ZooKeeper zooKeeper = new ZooKeeper("master:2181,node1:2181,node2:2181"
, 10 * 1000
, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("Zookeeper连接发送变动..正在执行Process函数");
}
}
);
String path = "/api";
Stat exists = zooKeeper.exists(path, false);
if (exists != null) {
// byte[] data = zooKeeper.getData(path, true, exists);
byte[] data = zooKeeper.getData(path, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("process被执行,监听生效");
}
}, exists
);
Thread.sleep(20 * 1000);
String dataRes = new String(data);
System.out.println(dataRes);
} else {
System.out.println("节点不存在...");
}
zooKeeper.close(3 * 1000);
/**
* 作业:
* 要求获取path路径下的所有子节点
*/
}
}
7、删除节点
public class Code06DeleteNode {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
ZooKeeper zooKeeper = new ZooKeeper("master:2181,node1:2181,node2:2181"
, 10 * 1000
, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("Zookeeper连接发送变动..正在执行Process函数");
}
}
);
String path = "/api";
Stat exists = zooKeeper.exists(path, false);
if (exists != null){
// Version 为 -1是表示是最新版本
zooKeeper.delete(path,-1);
}else {
System.out.println("节点不存在...");
}
zooKeeper.close(3*1000);
/**
* 作业2:创建一个DeleteAll函数实现递归删除所有节点
*/
}
}
作业:
1、要求获取path路径下的所有子节点
2、删除path路径下的所有子节点