zookeeper安装以及使用

1、zookeeper简介

zookeeper(以下简称ZK)是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop、Hbase、Kafka、Jstorm等开源软件的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等ZK的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。

2、zk集群安装(集群安装是奇数台)

ZK既可单节点运行,也可以多节点集群运行。生产环境都采用集群的方式,避免单节点故障。ZK需要java环境,要确保系统有jdk 1.7或更高版本。安装JDK这里就不演示了,我自己在虚拟机上安装,就安装了3个节点

https://zookeeper.apache.org/releases.html

我安装的版本是zookeeper-3.4.10,我解压到/app/soft目录下了

zookeeper安装以及使用_第1张图片

3、配置

zookeeper安装以及使用_第2张图片

zookeeper conf目录下有zoo_sample.cfg实例配置文件,复制这个文件,重命名为zoo.cfg,开始配置zoo.cfg的内容:

cp zoo_sample.cfg zoo.cfg

vi zoo.cfg

tickTime=2000  ##Client-Server通信心跳时间,单位是毫秒
initLimit=10   ##集群中的follower服务器(F)与leader服务器(L)之间初始连接时能容忍的最多心跳数
syncLimit=5    ##集群中的follower服务器与leader服务器之间请求和应答之间能容忍的最多心跳数
clientPort=2181   ## 监听端口
maxClientCnxns=100  ## 最大连接数
dataDir=/app/soft/zookeeper-3.4.10/data ## 数据目录
dataLogDir=/app/soft/zookeeper-3.4.10/log  ## 日志目录
server.1=192.168.34.128:2888:3888  ## zk节点1
server.2=192.168.34.129:2888:3888  ## zk节点2
server.3=192.168.34.130:2888:3888  ## zk节点3
在/app/soft/zookeeper-3.4.10/下创建两个文件夹,分别是data和log

然后分别在zk节点,/app/soft/zookeeper-3.4.10/data目录下,创建文本myid,内容分别是1、2、3序号

192.168.34.128 对应的是1

192.168.34.129 对应的是2

192.168.34.130 对应的是3

zookeeper安装以及使用_第3张图片

zookeeper安装以及使用_第4张图片

zookeeper安装以及使用_第5张图片

4、启动zk

启动之前,jdk7以上的版本一定要安装合适,然后在环境变量里配置ZK_HOME

zookeeper安装以及使用_第6张图片

然后在SecureCRT里同时打开三个节点

执行命令:zkServer.sh  start,这里的zkServer.sh是zookeeper bin目录下的脚本

zookeeper安装以及使用_第7张图片

看到这个结果不一定启动成功了,然后执行zkServer.sh  status 查看各个zk节点的状态,如果看到一个leader,其它两个节点都是follower说明启动成功了。


zookeeper安装以及使用_第8张图片

还可以通过查看jps命令去查看是否启动了zk

zookeeper安装以及使用_第9张图片

zkServer.sh stop是停掉zk节点服务的,到这里zk的启动就没有问题了!!!

5、zk选举leader

前面说到搭建zk集群节点是奇数台,因为只有是奇数它,它才能选举出谁是leader,谁是follwer,是通过前面配置的myid决定的,三个节点依次配置了1、2、3,服务器1启动,此时只有它一台服务器启动了,它发出去的报没有任何响应,所以它的选举状态一直是等待状态, 服务器2启动,它与最开始启动的服务器1进行通信,互相交换自己的选举结果,由于两者都没有历史数据,所以id值较大的服务器2胜出,但是由于没有达到超过半数以上的服务器都同意选举它,所以服务器1,2还是继续保持等待状态,服务器3启动,根据前面的理论分析,服务器3成为服务器1,2,3中的老大,而与上面不同的是,此时有三台服务器选举了它,所以它成为了这次选举的leader。

6、zk使用

启动zk之后,在任意一台服务上,运行:zkCli.sh进入zk的命令行模式

zookeeper安装以及使用_第10张图片

zk创建的节点叫znode,znode四种节点类型:持久节点、持久序列节点、暂时节点、暂时序列节点。

create   -e /app   111  创建一个暂时的znode节点

create   -s /app/test1  222  创建一个持久的,带有序列号的znode节点

zookeeper安装以及使用_第11张图片

get  /app/test  得到创建的节点中的数据

zookeeper安装以及使用_第12张图片

执行ls  /可以看到根节点下面所有子节点

zookeeper安装以及使用_第13张图片

ls /app/test watch  监听这个节点下的变化,我在另一个服务器下也打开了zk的命令行,


然后我在其它服务上,在这个节点下做创建节点的操作

zookeeper安装以及使用_第14张图片

会发现监听的服务器上会弹出下面消息,是对这个节点做出改变的通知

zookeeper安装以及使用_第15张图片

7、通过java代码来创建节点、修改节点内容、监听等

创建一个maven项目

pom.xml引入zk的jar包



    4.0.0

    zookeeperDemo
    zookeeperDemo
    1.0
    
        
            org.apache.zookeeper
            zookeeper
            3.4.10
        
        
            junit
            junit
            4.12
        
    

然后创建一个类

package cn.dl.zookeeper;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Tiger on 2018/7/5.
 */
public class ZookeeperClient {

    //连接的zk服务
    private static final String CONNECTION_HOSTS = "192.168.34.128:2181,192.168.34.128:2181,192.168.34.128:2181";
    //超时连接的时间
    private static final int SESSION_TIMEOUT = 2000;

    private static ZooKeeper zooKeeper = null;
    //servers根目录
    private volatile static  String serviceRootNode = "/services";
    //服务器列表
    /**使用volatile的意义
     * 1、通过在总线加LOCK#锁的方式
     * 2、通过缓存一致性协议
     * 1.volatile关键字的两层语义
     一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
     1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
     2)禁止进行指令重排序。
     * */
    private static volatile List serviceList = new ArrayList();
    static {
        try {
            zooKeeper = new ZooKeeper(CONNECTION_HOSTS, SESSION_TIMEOUT, new Watcher() {

                /**
                 * 监听服务器列表的变化
                 * */
                public void process(WatchedEvent watchedEvent) {
                    try {
                        getServerList();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取服务器列表
     * */
     public static void getServerList() throws Exception {
         List nodes = zooKeeper.getChildren(serviceRootNode,true);
         //清空服务器列表信息list集合
         serviceList.clear();
         for(String node : nodes){
             /**
              * 这里的第二个参数:false,意思是已经获到了连接,不需要重新获取连接
              * */
             byte[] data = zooKeeper.getData(serviceRootNode + "/"+ node,false,null);
             serviceList.add(new String(data));
         }
         System.out.println(serviceList);
     }
    public static void main(String[] args) throws Exception {
        ZookeeperClient zookeeperClient = new ZookeeperClient();
        zookeeperClient.getServerList();
        Thread.sleep(Long.MAX_VALUE);
    }
}
package cn.dl.zookeeper;


import org.apache.zookeeper.*;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Tiger on 2018/6/30.
 */
public class ZookeeperDemo {

    //连接的zk服务
    private static final String CONNECTION_HOSTS = "192.168.34.128:2181,192.168.34.128:2181,192.168.34.128:2181";
    //超时连接的时间
    private static final int SESSION_TIMEOUT = 2000;

    private static ZooKeeper zooKeeper = null;
    static {
        try {
            zooKeeper = new ZooKeeper(CONNECTION_HOSTS, SESSION_TIMEOUT, new Watcher() {
                public void process(WatchedEvent watchedEvent) {
                    System.out.println(watchedEvent.getPath()+";"+watchedEvent.getState());
                    try {
                        //获取对根目录节点数据的监控
                        zooKeeper.getChildren("/",true);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /*
     判断当前节点是否存在
     */
    public Stat isExistZnode(String path) throws Exception{
        Stat stat = zooKeeper.exists(path,true);
        return stat;
    }
    /*
      创建节点
     */
    @Test
    public String createZnode(String path, Object object, ArrayList zooDefs, CreateMode createMode) throws Exception {
        return  zooKeeper.create(path,object.toString().getBytes(),zooDefs,createMode);
    }
    /*
      修改节点
     */
    @Test
    public Stat updateZnode(String path, Object object, int version) throws Exception {
        return zooKeeper.setData(path,object.toString().getBytes(),version);
    }
    /*
      删除节点
     */
    @Test
    public void deleteZnode(String path,int version) throws Exception {
        zooKeeper.delete(path,version);
    }
    @Test
    public static void main(String[] args) throws Exception{
        ZookeeperDemo zookeeperDemo = new ZookeeperDemo();
        //创建节点
        if(zookeeperDemo.isExistZnode("/Tiger") == null){
            zookeeperDemo.createZnode("/Tiger","oh,my sky", ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
        }else {
            System.out.println("znode exist!!!");
        }
        //更新节点内容
        Stat stat = zookeeperDemo.isExistZnode("/Tiger");
        if(stat != null){
            System.out.println(stat.getVersion());
            zookeeperDemo.updateZnode("/Tiger","oh,my sky",stat.getVersion());
        }else{
            System.out.println("znode not exist !!!");
        }
        //删除节点
        Stat deleteStat = zookeeperDemo.isExistZnode("/Tiger1");
        if(deleteStat != null){
            zookeeperDemo.deleteZnode("/Tiger1",deleteStat.getVersion());
        }
        //获取根节点下所有子节点,遍历获取对应节点的数据
        List znodes = zooKeeper.getChildren("/",true);
        for(String path : znodes){
            System.out.println(path+">>>"+new String(zooKeeper.getData("/"+path,true,new Stat())));
        }
    }
}


zk的安装、简单使用就这些了,这是本人自己的理解,有什么不对的地方欢迎来吐槽!!!

你可能感兴趣的:(zookeeper)