Linux系统上安装zookeeper及三种zookeeper客户端的使用

主要说的内容有以下几点:

1、在linux上安装zookeepr

2、基本的操作命令

3、java中zookeeper三种客户端基本编写


1、在linux上安装zookeeper

       1、下载zookeeper安装包,下载地址

                链接:  https://pan.baidu.com/s/1r2co40V3PJGPZV4cOxC6rQ 

                密码:v4pa

        2、安装目录,一般我会将所有的软件安装在/usr/local/soft中,使用 cd /usr/local/soft 该命令找到需要下载的目录,将zookeeper安装包上传到该目录下。

cd /usr/local/soft

        3、使用该命令安装到当前目录下。

tar -zxvf apache-zookeeper-3.5.5-bin.tar.gz -C ./ 

         4、进入zookeeper文件夹,找到conf文件夹,将里面的 zoo_sample.cfg文件复制一份,将名字改为zoo.cfg。该文件就是zookeeper的配置文件。

//打开配置文件目录
cd apache-zookeeper-3.5.5-bin/conf/
//将配置文件复制一份,并改名为zoo.cfg
cp zoo_sample.cfg zoo.cfg

        5、修改完成后,进入到bin目录,启动zookeeper。

//进入zookeeper的命令目录
cd ..
cd bin/

//启动zookeeper
./zkServer.sh start

//关闭zookeeper
./zkServer.sh stop

//查看zookeeper状态
./zkServer.sh status

至此zookeeper安装完成。

2、基本操作命令

        zookeeper是一种类似于操作系统的文件系统数据结构,每个节点被称为znode,这个znode是可以存储数据的。

节点分为两大种,一种是持久化节点,一种是临时节点;

持久化节点又分为顺序持久化节点和持久化节点;

临时节点也分为顺序临时节点和临时节点。

当连接断掉后,所有的临时节点全部失效被删除;持久化节点则不会发生变化。

永久节点又分为顺序节点

        1、安装好zookeeper后,可以使用命令进行查看是否启动成功。

//查看zookeeper是否启动
ps -ef | grep zookeeper

        2、在bean目录下连接zookeeper

//打开zookeeper连接命令
./zkCli.sh

        Linux系统上安装zookeeper及三种zookeeper客户端的使用_第1张图片

        创建节点

//创建节点 -e(创建临时节点,不加则创建永久节点) /xaioabi(节点名) 测试创建节点 (节点存放的目录)
create -e /xiaobai 测试创建节点
create -e /xiaobai/test01 123456

需要注意的一点是,节点只能一级一级创建,不能直接创建多级节点

//查看根目录节点
ls /
//查看xiaobai子节点
ls /xiaobai

//退出会话
//关闭当前会话
close
//关闭当前连接
quit

//修改节点数据
//修改test01节点数据
set /xiaoabi/test01 13579
//查看节点数据
get /xiaobai/test01

// 删除节点
//删除节点(只能删除没有子节点的节点,如果有的话,要先删除子节点才能删除该节点)
delete /xiaobai/test01
//删除根目录下所有没有子节点的节点
deleteall /

需要注意的是:

        删除的节点有子节点,

        如果子节点数据为空,使用deleteall可以进行删除;

        如果子节点有数据,则会删除失败

3、java中zookeeper的三种客户端使用

java中使用zookeeper客户端有三种方式:

1、zookeeper:zookeeper提供的是原生java客户端

2、zkClient:在原生zookeeper基础上进行扩展的第三方java客户端

3、curator:Netflix公司在原生zookeeper基础上开源的java客户端

        1、zookeeper原生客户端

                zookeeper原生客户端是官方提供的,此客户端所有的东西都需要自己手写,包括创建连接,手写增删改查语句。由于此客户端属于纯原生,所有东西都必须自己写,所以一般不会使用该客户端进行开发。

        该客户端的弊端有一下几种:

                1、会话的连接是异步的。如果创建连接,只有等监听连接成功后才可以进行操作;

                2、Zookeeper的Watcher是一次性的,每次触发之后都需要重新进行注册;

                3、Session超时之后没有重连机制;

                4、异常处理繁琐,zookeeper提供了很多的异常。对于开发人员来说可能对这些异常都不知道如何处理;

                5、只提供了简单的byte[]接口,没有提供对象级别的序列化;

                6、开发的复杂性。创建节点前需要判断该节点是否存在;多级删除节点不支持,只能一级一级进行删除等等;

        需要添加的依赖:

 
        
        
            org.apache.zookeeper
            zookeeper
            3.5.5
        
 

编写测试代码: 

package com.bpc.client;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
 * @author xiaobai
 */
public class ZookeeperClientTest01 {
    private static final String ZK_ADDRESS = "127.0.0.1:2181";
    private ZooKeeper zooKeeper;
    private Integer sessionTimeout;

    /**
     * 删除节点
     */
    public void deletePath(String path) throws KeeperException, InterruptedException {
        //判断该节点下面是否有子节点,有子节点删除子节点
        List childrenPathList = getChildrenPath(path);
        if (!childrenPathList.isEmpty()) {
            //删除子节点
            for (String childrenPath : childrenPathList) {
                //迭代删除子节点
                deletePath(path + "/" + childrenPath);
            }
        }
        zooKeeper.delete(path, -1);
        System.out.println("删除节点:" + path + "成功!");
        return;
    }
    /**
     * 获取所有子节点名称
     */
    public List getChildrenPath(String path) throws KeeperException, InterruptedException {
        //判断该节点是否有子节点
        int numChildren = getNumChildren(path);
        if (0 == numChildren) {
            return new ArrayList<>();
        }
        return zooKeeper.getChildren(path, false);
    }
    /**
     * 修改节点内容
     */
    public void setContent(String path, String content) throws KeeperException, InterruptedException {
        //节点名称、修改内容,版本号(-1表示所有版本号都匹配)
        zooKeeper.setData(path, content.getBytes(), -1);
    }
    /**
     * 获取节点子节点数量
     */
    public int getNumChildren(String path) throws KeeperException, InterruptedException {
        //存放节点状态信息
        Stat stat = isExist(path);
        return stat == null ? 0 : stat.getNumChildren();
    }
    /**
     * 获取节点内容
     */
    public String getPath(String path) throws KeeperException, InterruptedException {
        //存放节点状态信息
        Stat stat = new Stat();
        byte[] data = zooKeeper.getData(path, false, stat);
        return new String(data);
    }
    /**
     * 检查节点是否存在
     */
    public Stat isExist(String path) throws KeeperException, InterruptedException {
        //节点名称、是否观察
        Stat stat = zooKeeper.exists(path, false);
        return stat;
    }
    /**
     * 创建节点
     */
    public String createNode(String path, String content) throws KeeperException, InterruptedException {
        //节点名称;节点存储内存数据;权限;节点状态(持久性节点)
        String pathNode = zooKeeper.create(path, content.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println("创建节点的结果:" + pathNode);
        return pathNode;
    }
    /**
     * 关闭会话连接
     */
    public void close() throws InterruptedException {
        zooKeeper.close();
    }
    /**
     * 获取连接
     */
    public ZooKeeper getConnect(int sessionTimeout) throws IOException, InterruptedException {
        //倒计数器,倒数1个
        CountDownLatch countDownLatch = new CountDownLatch(1);
        //创建zooKeeper对象
        //参数:连接地址和端口;会话超时时间(该连接保持时间);观察者对象(用来观察连接过程)
        ZooKeeper zooKeeper = new ZooKeeper(ZK_ADDRESS, sessionTimeout, (WatchedEvent event) -> {
            //判断状态是否是已连接
            if (Watcher.Event.KeeperState.SyncConnected.equals(event.getState())) {
                System.out.println("连接成功。。。。");
                //zookeeper连上了
                countDownLatch.countDown();
            }
        });
        //连接成功后返回zookeeper对象
        countDownLatch.await();
        return zooKeeper;
    }
    public ZookeeperClientTest01(Integer sessionTimeout) throws IOException, InterruptedException {
        this.sessionTimeout = sessionTimeout;
        this.zooKeeper = getConnect(sessionTimeout);
    }
    public ZooKeeper getZooKeeper() {  return zooKeeper;   }
    public void setZooKeeper(ZooKeeper zooKeeper) { this.zooKeeper = zooKeeper;}
    public Integer getSessionTimeout() {  return sessionTimeout; }
    public void setSessionTimeout(Integer sessionTimeout) {this.sessionTimeout = sessionTimeout;}
}

测试一下:

 public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        //节点名称
        String path = "/test02";
        //创建对象并获取连接
        ZookeeperClientTest01 test01 = new ZookeeperClientTest01(5000);

        //检查节点是否存在
        Stat isExist = test01.isExist(path);
        if (null == isExist) {
            //创建节点
            test01.createNode(path, "创建节点内容");
            //创建子节点
            test01.createNode(path+"/test02","创建子节点001");
        }
        //获取节点
        String pathContent = test01.getPath(path);
        System.out.println("节点存放的内容:" + pathContent);
        //修改节点内容
        test01.setContent(path, "修改节点内容");
        //获取该节点下的所有子节点
        List childrenPathList = test01.getChildrenPath(path);
        for (String childrenPath : childrenPathList) {
            System.out.println("子节点名称:" + childrenPath);
        }
        //删除节点
        test01.deletePath(path);
        //关闭会话
        test01.close();

    }

       

2、zkClient客户端

        zkClient客户端是在原生zookeeper客户端上进行扩展的第三方开源客户端。该客户端在前几年被经常使用。

        该客户端的优点:

        1、提供了对象序列化的方式;

        2、添加了session超时重试机制;

        3、Wacther实现了反复注册;

        4、对crud(增删改查)进行了封装处理;例如:提供了迭代删除接口等等;

        该客户端的弊端:

                1、几乎没有参考文档;

                2、session超时重试机制比较难用

                3、没有提供各种场景的实现

        需要导入的依赖:

 
 
     com.101tec
     zkclient
     0.11

编写测试代码:

package com.bpc.client;
import org.I0Itec.zkclient.ZkClient;
import java.util.List;
/**
 * @author xiaobai
 */
public class Test02 {
    public static void main(String[] args) {
        String ZK_ADDRESS = "127.0.0.1:2181";
        String path = "/test04";
        //创建连接
        ZkClient zkClient = new ZkClient(ZK_ADDRESS);
        //检查节点是否存在(节点名称)
        boolean isExist = zkClient.exists(path);
        //节点不存在则添加
        if (!isExist) {
            //创建节点(节点名称、节点内容)
            zkClient.createPersistent(path, "创建节点test004");
            //创建子节点(节点名称、节点内容)
            zkClient.createPersistent(path + "/znode01", "创建子节点znode01");
        }
        //获取节点数据(节点名称)
        String content = zkClient.readData(path);
        System.out.println("节点存储的数据:" + content);
        //修改节点内容(节点名称、节点内容)
        zkClient.writeData(path, "修改节点内容成功!");
        //获取所以子节点(节点名称)
        List childrenList = zkClient.getChildren(path);
        for (String children : childrenList) {
            System.out.println("获取子节点名称:" + children);
        }
        //删除单节点删除(节点名称)
        boolean delete = zkClient.delete(path + "/znode01");
        System.out.println("删除单节点是否成功:" + delete);
        //递归删除多级节点(节点名称)
        boolean deleteAll = zkClient.deleteRecursive(path);
        System.out.println("删除多级节点是否成功:" + deleteAll);
    }
}

        3、curator客户端

                curator客户端是目前官方推荐的,不管是从性能还是封装来说是目前比较好的框架。该框架是Netflix公司开发的开源框架,捐献给Apache后,成为Apache开源框架。相比于zookeeper客户端,进行了高度的封装和抽象,解决了非常底层的细节开发工作,包括超时重连机制、反复注册Watcher、NodeExistsException异常等等。并且提供了一套可读性和易用性的Fluent风格的API接口。

curator客户端的优点:

        1、提供了一套Fluent风格的API接口,大大提高了可读性和易用性;

        2、解决Watcher注册一次就会失效的问题,实现了Wacther反复注册;

        3、提供了不同场景的抽象封装,例如:共享锁服务、Master选举机制和分布式计算器等场景;

        4、更加倾向于开发人员,例如:链式调用风格、分布式锁、zookeeper工具类等等;

        5、该框架为我们封装了很多逻辑和方法,使得框架的容错性大大提供。使得我们开发人员更专注于业务。

需要导入的依赖:



     org.apache.curator
     curator-framework
     4.2.0



     org.apache.curator
     curator-recipes
     4.2.0

编写测试代码:

public static void main(String[] args) throws Exception {
        String path = "/test05";
        CuratorTest03 curator = new CuratorTest03();

        //检查节点是否存在
        Stat stat = curator.client.checkExists().forPath(path);
        if (null == stat) {
            //创建节点
            curator.client.create()
                    .creatingParentsIfNeeded()
                    .withMode(CreateMode.PERSISTENT)
                    .forPath(path, "创建节点test05".getBytes());
            //创建子节点
            curator.client.create()
                    .creatingParentsIfNeeded()
                    .withMode(CreateMode.PERSISTENT)
                    .forPath(path + "/test01", "创建子节点test01".getBytes());
            curator.client.create()
                    .creatingParentsIfNeeded()
                    .withMode(CreateMode.PERSISTENT)
                    .forPath(path + "/test02", "创建子节点test02".getBytes());
        }
        //修改节点数据
        curator.client.setData().forPath(path, "修改主节点数据内容".getBytes());
        //获取节点数据
        String node = new String(curator.client.getData().forPath(path));
        String test01Node = new String(curator.client.getData().forPath(path + "/test01"));
        System.out.println("主节点数据:" + node);
        System.out.println("子节点Test01数据:" + test01Node);
        //获取所有子节点
        List childrenList = curator.client.getChildren().forPath(path);
        for (String children : childrenList) {
            System.out.println("子节点名称:" + children);
        }
        //单个节点删除
        curator.client.delete().forPath(path + "/test02");
        //迭代删除节点
        curator.client.delete().deletingChildrenIfNeeded().forPath(path);
        //查看节点是否存在
        Stat stat1 = curator.client.checkExists().forPath(path);
        if (null == stat1) {
            System.out.println(path + "节点不存在");
        } else {
            System.out.println(path + "该节点存在");
        }
    }

你可能感兴趣的:(zookeeper,java,linux)