大数据 之 Zookeeper(Zookeeper 实战【重点】)

三、Zookeeper实战(开发重点)

3.1 分布式安装部署

1)集群规划

​ 在 hadoop105、hadoop106 和 hadoop107 三个节点上部署 Zookeeper。

2)解压安装

(1)解压Zookeeper安装包到/opt/module/目录下,并可以自定义名称

[xiaoxq@hadoop105 software]$ tar -zxvf zookeeper-3.5.7.tar.gz -C /opt/module/

[xiaoxq@hadoop105 module]$ mv apache-zookeeper-3.5.7-bin.tar.gz zookeeper-3.5.7

(2)同步/opt/module/zookeeper-3.5.7目录内容到hadoop106、hadoop107

[xiaoxq@hadoop105 module]$ xsync zookeeper-3.5.7/

3)配置服务器编号

(1)在/opt/module/zookeeper-3.5.7/这个目录下创建zkData

[xiaoxq@hadoop105 zookeeper-3.5.7]$ mkdir -p zkData

(2)在/opt/module/zookeeper-3.5.7/zkData目录下创建一个myid的文件

[xiaoxq@hadoop105 zkData]$ touch myid

​ 添加myid文件,注意一定要在linux里面创建,在notepad++里面很可能乱码

(3)编辑myid文件

[xiaoxq@hadoop105 zkData]$ vi myid

在文件中添加与server对应的编号:

5

(4)拷贝配置好的zookeeper到其他机器上

[xiaoxq@hadoop105 zkData]$ xsync myid

并分别在hadoop106、hadoop107 上修改myid文件中内容为 6、7

4)配置zoo.cfg文件

(1)重命名/opt/module/zookeeper-3.5.7/conf这个目录下的zoo_sample.cfg为zoo.cfg

[xiaoxq@hadoop105 conf]$ mv zoo_sample.cfg zoo.cfg

(2)打开zoo.cfg文件

[xiaoxq@hadoop105 conf]$ vim zoo.cfg

修改数据存储路径配置

dataDir=/opt/module/zookeeper-3.5.7/zkData

增加如下配置

#######################cluster##########################
server.5=hadoop105:2888:3888
server.6=hadoop106:2888:3888
server.7=hadoop107:2888:3888

(3)同步zoo.cfg配置文件

[xiaoxq@hadoop105 conf]$ xsync zoo.cfg

(4)配置参数解读

server.A=B:C:D。

A是一个数字,表示这个是第几号服务器;

​ 集群模式下配置一个文件 myid,这个文件在 dataDir 目录下,这个文件里面有一个数据就是A的值,Zookeeper 启动时读取此文件,拿到里面的数据与 zoo.cfg 里面的配置信息比较从而判断到底是哪个 server。

B是这个服务器的地址;

C是这个服务器 Follower 与集群中的 Leader 服务器交换信息的端口

D是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。

5)集群操作

(1)分别启动Zookeeper

[xiaoxq@hadoop105 zookeeper-3.5.7]$ bin/zkServer.sh start
[xiaoxq@hadoop106 zookeeper-3.5.7]$ bin/zkServer.sh start
[xiaoxq@hadoop107 zookeeper-3.5.7]$ bin/zkServer.sh start

(2)查看状态

[xiaoxq@hadoop105 zookeeper-3.5.7]$ bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower

[xiaoxq@hadoop106 zookeeper-3.5.7]$ bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: follower

[xiaoxq@hadoop107 zookeeper-3.5.7]$ bin/zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/module/zookeeper-3.5.7/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost.
Mode: leader

3.2 客户端命令行操作

命令基本语法 功能描述
help 显示所有操作命令
ls path 使用 ls 命令来查看当前znode的子节点-w 监听子节点变化-s 附加次级信息
create 普通创建-s 含有序列-e 临时(重启或者超时消失)
get path 获得节点的值-w 监听节点内容变化-s 附加次级信息
set 设置节点的具体值
stat 查看节点状态
delete 删除节点
deleteall 递归删除节点

1)启动客户端

[xiaoxq@hadoop105 zookeeper-3.5.7]$ bin/zkCli.sh 

WatchedEvent state:SyncConnected type:None path:null
[zk: localhost:2181(CONNECTED) 0] 

2)显示所有操作命令

[zk: localhost:2181(CONNECTED) 0] help

3)查看当前znode中所包含的内容

[zk: localhost:2181(CONNECTED) 1] ls /
[zookeeper]

4)查看当前节点详细数据

[zk: localhost:2181(CONNECTED) 2] ls -s /
[zookeeper]cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1

5)分别创建2个普通节点

[zk: localhost:2181(CONNECTED) 4] create /xiyouji "wukong"
Created /xiyouji
[zk: localhost:2181(CONNECTED) 5] create /xiyouji/tianting "yudi"
Created /xiyouji/tianting

6)获得节点的值

[zk: localhost:2181(CONNECTED) 6] get /xiyouji
wukong

[zk: localhost:2181(CONNECTED) 7] get -s /xiyouji
wukong
cZxid = 0x100000002
ctime = Mon Jul 27 20:14:59 CST 2020
mZxid = 0x100000002
mtime = Mon Jul 27 20:14:59 CST 2020
pZxid = 0x100000003
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 1

[zk: localhost:2181(CONNECTED) 8] get -s /xiyouji/tianting
yudi
cZxid = 0x100000003
ctime = Mon Jul 27 20:17:48 CST 2020
mZxid = 0x100000003
mtime = Mon Jul 27 20:17:48 CST 2020
pZxid = 0x100000003
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0

7)创建临时节点

[zk: localhost:2181(CONNECTED) 9] create -e /xiyouji/lingshan "rulai"
Created /xiyouji/lingshan

(1)在当前客户端是能查看到的

[zk: localhost:2181(CONNECTED) 10] ls /xiyouji
[lingshan, tianting]

(2)退出当前客户端然后再重启客户端

[zk: localhost:2181(CONNECTED) 11] quit
[xiaoxq@hadoop105 zookeeper-3.5.7]$ bin/zkCli.sh 

(3)再次查看根目录下短暂节点已经删除(lingshan)

[zk: localhost:2181(CONNECTED) 0] ls /xiyouji
[tianting]

8)创建带序号的节点

(1)先创建一个普通的根节点/xiyouji/donghai

[zk: localhost:2181(CONNECTED) 1] create /xiyouji/donghai "longwang"
Created /xiyouji/donghai

(2)创建带序号的节点

[zk: localhost:2181(CONNECTED) 2] create /xiyouji/donghai "longwang"
Node already exists: /xiyouji/donghai
[zk: localhost:2181(CONNECTED) 3] create -s /xiyouji/donghai "longwang"
Created /xiyouji/donghai0000000003
[zk: localhost:2181(CONNECTED) 4] create -s /xiyouji/donghai "longwang"
Created /xiyouji/donghai0000000004
[zk: localhost:2181(CONNECTED) 5] ls /xiyouji
[donghai, donghai0000000003, donghai0000000004, tianting]

如果节点下原来没有子节点,序号从0开始依次递增。如果原节点下已有2个节点,则再排序时从2开始,以此类推。

9)修改节点数据值

[zk: localhost:2181(CONNECTED) 6] set /xiyouji/donghai "guichengxiang"

[zk: localhost:2181(CONNECTED) 8] get /xiyouji/donghai
guichengxiang

10)节点的值变化监听

(1)在 hadoop105 主机上注册监听 /xiyouji 节点

[zk: localhost:2181(CONNECTED) 9] get -w /xiyouji
wukong

(2)在 hadoop106 主机上修改/xiyouji节点的数据

[zk: localhost:2181(CONNECTED) 0] set /xiyouji "xiabing"

(3)观察 hadoop105 主机收到数据变化的监听

[zk: localhost:2181(CONNECTED) 10] 
WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/xiyouji

11)节点的子节点变化监听(路径变化)

(1)在hadoop106主机上注册监听/xiyouji节点的子节点变化

[zk: localhost:2181(CONNECTED) 1] ls -w /xiyouji
[donghai, donghai0000000003, donghai0000000004, tianting]

(2)在hadoop105主机/xiyouji节点上创建子节点

[zk: localhost:2181(CONNECTED) 10] create /xiyouji/huaguozan "houzi"
Created /xiyouji/huaguozan

(3)观察hadoop106主机收到子节点变化的监听

[zk: localhost:2181(CONNECTED) 2] 
WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/xiyouji

12)删除节点

[zk: localhost:2181(CONNECTED) 2] delete /xiyouji/huaguozan

13)递归删除节点

[zk: localhost:2181(CONNECTED) 4] deleteall /xiyouji/tianting

14)查看节点状态

[zk: localhost:2181(CONNECTED) 6] stat /xiyouji
cZxid = 0x100000002
ctime = Mon Jul 27 20:14:59 CST 2020
mZxid = 0x10000000e
mtime = Mon Jul 27 20:31:32 CST 2020
pZxid = 0x100000011
cversion = 9
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 7
numChildren = 3

3.3 API 应用

3.3.1 IDEA环境搭建

1)创建一个MavenModule

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

3.3.2 初始化 ZooKeeper 客户端

public class ZkClient {

    private String connectString;
    private int sessoinTimeout;
    private ZooKeeper zkClient;

    //1.获取客户端对象
    @Before
    public void init() throws IOException {
        connectString = "hadoop105:2181,hadoop106:2181,hadoop107:2181";
        sessoinTimeout = 4000;
        //参数解读 1集群连接字符串  2连接超时时间 单位:毫秒  3当前客户端默认的监控器
        zkClient = new ZooKeeper(connectString, sessoinTimeout, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {

            }
        });
    }

    @After
    public void close() throws InterruptedException {
        //3.关闭客户端对象
        zkClient.close();

    }

}

3.3.3 获取子节点列表,不监听

@Test
public void ls() throws IOException, KeeperException, InterruptedException {
    //2.用客户端对象做各种操作
    List<String> children = zkClient.getChildren("/", false);
    System.out.println(children);
}

运行结果

[zk: localhost:2181(CONNECTED) 0] ls /
[xiyouji, zookeeper]

在这里插入图片描述

3.3.4 获取子节点列表,并监听

@Test
    public void getAndWatch() throws KeeperException, InterruptedException {
        //判断节点是否存在
        Stat stat = zkClient.exists("/xiyouji", false);
        if (stat == null){
            System.out.println("节点不存在");
            return;
        }
        //节点存在
        byte[] data = zkClient.getData("/xiyouji", new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                System.out.println(event);
            }
        }, stat);
        System.out.println(new String(data));
        //线程阻塞,睡眠
        Thread.sleep(Long.MAX_VALUE);
    }

3.3.5 创建子节点

@Test
    public void getAndWatch() throws KeeperException, InterruptedException {
        //判断节点是否存在
        Stat stat = zkClient.exists("/xiyouji", false);
        if (stat == null){
            System.out.println("节点不存在");
            return;
        }
        //节点存在
        byte[] data = zkClient.getData("/xiyouji", new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                System.out.println(event);
            }
        }, stat);
        System.out.println(new String(data));
        //线程阻塞,睡眠
        Thread.sleep(Long.MAX_VALUE);
    }

3.3.6 判断Znode是否存在

@Test
public void exist() throws Exception {

	Stat stat = zkClient.exists("/xiyouji", false);

	System.out.println(stat == null ? "not exist" : "exist");
}

3.3.7 获取子节点存储的数据,不监听

@Test
public void get() throws KeeperException, InterruptedException {
    //判断节点是否存在
    Stat stat = zkClient.exists("/xiyouji", false);
    if (stat == null) {
        System.out.println("节点不存在...");
        return;
    }

    byte[] data = zkClient.getData("/xiyouji", false, stat);
    System.out.println(new String(data));
}

3.3.8 获取子节点存储的数据,并监听

@Test
public void getAndWatch() throws KeeperException, InterruptedException {
    //判断节点是否存在
    Stat stat = zkClient.exists("/xiyouji", false);
    if (stat == null) {
        System.out.println("节点不存在...");
        return;
    }

    byte[] data = zkClient.getData("/xiyouji", new Watcher() {
        @Override
        public void process(WatchedEvent event) {
            System.out.println(event);
        }
    }, stat);
    System.out.println(new String(data));
    //线程阻塞
    Thread.sleep(Long.MAX_VALUE);
}

3.3.9设置节点的值

@Test
public void set() throws KeeperException, InterruptedException {
    //判断节点是否存在
    Stat stat = zkClient.exists("/xiyouji", false);
    if (stat == null) {
        System.out.println("节点不存在...");
        return;
    }
    //参数解读 1节点路径 2节点的值 3版本号
    zkClient.setData("/xiyouji", "nverguo".getBytes(), stat.getVersion());
}

3.3.10删除空节点

@Test
public void delete() throws KeeperException, InterruptedException {
    //判断节点是否存在
    Stat stat = zkClient.exists("/aaa", false);
    if (stat == null) {
        System.out.println("节点不存在...");
        return;
    }
    zkClient.delete("/aaa", stat.getVersion());
}

3.3.11 删除非空节点,递归实现

//封装一个方法,方便递归调用
public void deleteAll(String path, ZooKeeper zk) throws KeeperException, InterruptedException {
    //判断节点是否存在
    Stat stat = zkClient.exists(path, false);
    if (stat == null) {
        System.out.println("节点不存在...");
        return;
    }
    //先获取当前传入节点下的所有子节点
    List<String> children = zk.getChildren(path, false);
    if (children.isEmpty()) {
        //说明传入的节点没有子节点,可以直接删除
        zk.delete(path, stat.getVersion());
    } else {
        //如果传入的节点有子节点,循环所有子节点
        for (String child : children) {
            //删除子节点,但是不知道子节点下面还有没有子节点,所以递归调用
            deleteAll(path + "/" + child, zk);  
        }
        //删除完所有子节点以后,记得删除传入的节点
        zk.delete(path, stat.getVersion());
    }
}
//测试deleteAll
@Test
public void testDeleteAll() throws KeeperException, InterruptedException {
    deleteAll("/xiyouji",zkClient);
}

猜你喜欢

转载自blog.csdn.net/weixin_48067943/article/details/107650033