目录
3. 在ZK的安装目录下的zkData目录中创建一个myid的文件
4. 将hadoop102的整个ZK的安装目录分发到其他机器
一、ZK的集群搭建和使用
注意事项:如果不是第一次搭建集群,那么就把zk安装目录下的zkData目录删除,并且把logs目录也删除
1. 在ZK的安装目录下创建 zkData
2. 修改zoo.cfg 配置文件
--
dataDir=/opt/module/zookeeper-3.5.7/zkData
--
server.2=hadoop102:2888:3888
server.3=hadoop103:2888:3888
server.4=hadoop104:2888:3888
zookeeper上hosts映射不了,只能写全ip地址这样才能启动zookeeper
3. 在ZK的安装目录下的zkData目录中创建一个myid的文件
用于标记当前服务器的编号
hadoop102 --> 2
hadoop103 --> 3
hadoop104 --> 4
4. 将hadoop102的整个ZK的安装目录分发到其他机器
5. 在不同机器上修改myid文件中的值
二、自定义群启群停zk服务的脚本zk_cluster.sh
#!/bin/bash
#检验参数
if [ $# -lt 1 ]
then
echo '参数不能为空!!!'
exit
fi
#循环遍历每一台机器,分别启动或者停止ZK服务
for host in hadoop102 hadoop103 hadoop104
do
case $1 in
"start")
echo "*****************start $host zookeeper****************"
ssh $host /opt/module/zookeeper-3.5.7/bin/zkServer.sh $1
;;
"stop")
echo "*****************stop $host zookeeper****************"
ssh $host /opt/module/zookeeper-3.5.7/bin/zkServer.sh $1
;;
"status")
echo "*****************status $host zookeeper****************"
ssh $host /opt/module/zookeeper-3.5.7/bin/zkServer.sh $1
;;
*)
echo '参数有误!!!'
exit
;;
esac
done
zk_cluster.sh start
zk_cluster.sh status
三、客户端命令行操作
命令基本语法 | 功能描述 |
help | 显示所有操作命令 |
ls path | 使用 ls 命令来查看当前znode的子节点 -w 监听子节点变化 -s 附加次级信息 |
create | 普通创建 -s 含有序列 -e 临时(重启或者超时消失) |
get path | 获得节点的值 -w 监听节点内容变化 -s 附加次级信息 |
set | 设置节点的具体值 |
stat | 查看节点状态 |
delete | 删除节点 |
deleteall | 递归删除节点 |
四、API应用
1)创建一个Maven Module
2)添加pom文件
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.7</version>
</dependency>
</dependencies>
3)拷贝log4j.properties文件到项目根目录
需要在项目的src/main/resources目录下,新建一个文件,命名为“log4j.properties”,在文件中填入。
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
4)初始化ZooKeeper客户端
/**
* 1、获取ZK客户端链接对象
* 2、调用相关API完成对应的功能
* 3、关闭资源
*/
public class ZookeeperTest {
private ZooKeeper zk;
……
链接zk服务
/**
* connectString:链接zk服务的地址 hadoop102:2181,hadoop103:2181,hadoop104:2181
* sessionTimeout:超时时间(10000-40000)
*/
@Test
public void testCreateZookeeperClient() throws IOException, InterruptedException {
String connectStr = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
int sessionTimeout = 10000;
ZooKeeper zooKeeper = new ZooKeeper(connectStr, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("根据具体的业务进行下一步操作。");
}
});
System.out.println("zk:**************"+zooKeeper);
zooKeeper.close();
}
初始化ZK客户端
/**
* 创建节点
* 1.path:指定创建节点的路径
* 2.data:指定要创建的节点下的数据
* 3.acl:对操作用户的权限控制
* 4.CreateMode:指定当前节点的类型(持久化/临时/(序列))
*/
@Test
public void testCreate() throws InterruptedException, KeeperException {
zk.create("/xiyou",
"rulai".getBytes(StandardCharsets.UTF_8),
ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
}
/**
* 获取链接对象
*/
@Before
public void init() throws IOException {
String connectStr = "hadoop102:2181,hadoop103:2181,hadoop104:2181";
int sessionTimeout = 10000;
zk = new ZooKeeper(connectStr, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
// System.out.println("根据具体的业务进行下一步操作。");
}
});
}
/**
* 关闭链接
* @throws InterruptedException
*/
@After
public void close() throws InterruptedException {
zk.close();
}
5)获取子节点
/**
* 获取子节点
*/
@Test
public void testgetChild() throws InterruptedException, KeeperException {
//获取子节点(不监控)
// List<String> children = zk.getChildren("/", false);
List<String> children = zk.getChildren("/", new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("发现根目录下的节点有变化。。。");
}
});
for (String child : children){
System.out.println(child);
}
//线程休眠
Thread.sleep(Long.MAX_VALUE);
}
6)获取节点的数据
首先判断节点是否存在
/**
* 获取节点是否存在
*/
@Test
public void testExist() throws InterruptedException, KeeperException {
Stat stat = zk.exists("/sanguo", false);
if (stat == null){
System.out.println("不存在");
}else {
System.out.println("存在");
}
}
/**
* 获取节点的数据
* @throws InterruptedException
* @throws KeeperException
*/
@Test
public void testGetData() throws InterruptedException, KeeperException {
//封装path
String path = "/sanguo";
//1.判断节点是否存在
Stat stat = zk.exists(path, false);
if (stat == null){
System.out.println("不存在");
}else {
//2.节点存在再获取数据
//System.out.println("存在");
byte[] datas = zk.getData(path, false, stat);
System.out.println(new String(datas));
}
}
7)修改节点下的内容
/**
*修改节点下的内容
* @throws InterruptedException
* @throws KeeperException
*/
@Test
public void testSetData() throws InterruptedException, KeeperException {
//封装path
String path = "/sanguo";
//1.判断节点是否存在
Stat stat = zk.exists(path, false);
if (stat == null){
System.out.println("不存在");
}else {
//2.节点存在再修改据
//System.out.println("存在");
zk.setData(path,"guanyu,zhangfei".getBytes(StandardCharsets.UTF_8), stat.getVersion());
//-1:不检测版本
// zk.setData(path,"guanyu,zhangfei".getBytes(StandardCharsets.UTF_8), -1);
}
}
8)删除空节点(无子节点)
/**
* 删除空节点(没有子节点)
* @throws InterruptedException
* @throws KeeperException
*/
@Test
public void testDelete() throws InterruptedException, KeeperException {
//封装path
String path = "/sanguo";
//1.判断节点是否存在
Stat stat = zk.exists(path, false);
if (stat == null){
System.out.println("不存在");
}else {
//2.删除空节点(没有子节点)
//System.out.println("存在");
zk.delete(path,stat.getVersion());
}
}
9)删除非空节点(有子节点)
/**
* 测试递归删除
* @throws InterruptedException
* @throws KeeperException
*/
@Test
public void testDeleteAll() throws InterruptedException, KeeperException {
deleteAll("/a",zk);
}
/**
* 递归删除节点(有子节点)
*/
public void deleteAll(String path,ZooKeeper zk) throws InterruptedException, KeeperException {
//1.判断节点是否存在
Stat stat = zk.exists(path, false);
if (stat == null){
System.out.println("不存在");
return;
}else {
//2.判断有无子节点
//System.out.println("存在");
List<String> children = zk.getChildren(path, false);
if (children.isEmpty()){
//没有子节点直接删除
zk.delete(path,stat.getVersion());
} else {
//递归调用自己,先把所有的子节点删除
for (String child:children){
deleteAll(path+"/"+child,zk);
}
//最后删除自己
deleteAll(path, zk);
}
}
}