Zookeeper

Zookeeper概念

Zookeeper 是 Apache Hadoop 项目下的一个子项目,是一个树形目录服务。

Zookeeper 翻译过来就是动物园管理员,他是用来管Hadoop(大象)、Hive(蜜蜂)、Pig(小猪)的管理员。简称zk

Zookeeper 是一个分布式的、开源的分布式应用程序的协调服务。

Zookeeper提供的主要功能包括

配置管理

分布式锁

集群管理

Zookeeper数据模型

ZooKeeper是一个树形目录服务,其数据模型和Unix的文件系统目录树很类似,拥有一个层次化结构。

这里面的每一个节点都被称为: ZNode,每个节点上都会保存自己的数据和节点信息。

节点可以拥有子节点,同时也允许少量(1MB)数据存储在该节点之下。

节点可以分为四大类:

PERSISTENT持久化节点

EPHEMERAL 临时节点: -e

PERSISTENT SEQUENTIAL 持久化顺序节点:-s

EPHEMERAL SFOUENTIAL临时顺序节点: -es

 

 Zookeeper服务端常用命令

启动ZooKeeper服务: ./zkServer.sh start

查看 ZooKeeper服务状态: ./zkServer.sh status

停止 ZooKeeper服务: /zkServer.sh stop

重启 ZooKeeper服务: ./zkServer.sh restart

 Zookeeper客户端常用命令

本机启动./zkCli.sh -server localhost:2181

create /app1 shun 

get  /app1

delete /app1

set /app1 shun2

ls /

创建子节点

create /app1/p1

create /app1/p2

deleteall /app1 删除全部节点包括子节点

help帮助

 


Corator介绍

Curator Apache ZooKeeper 的Java客户端库。

常见的ZooKeeper Java API :

原生Java API

ZkClient

Curator

Curator 项目的目标是简化 ZooKeeper客户端的使用。

Curator最初是 Netfix 研发的,后来捐献了Apache基金会,目前是Apache的顶级项目。 

官网: http://curator.apache.org/

Curator API常用操作

建立连接

添加节点

删除节点

修改节点

查询节点

Watch事件

监听

分布式锁实现

建立连接

pom文件

    <dependencies>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>

        <!--curator-->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.0.0</version>
        </dependency>
        <!--日志-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.21</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
        </dependency>

    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

test测试目录下创建连接

package com.itheima.curator;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.Test;

public class CuratorTest {
    @Test
    public void testConnect(){


        /**
         *@param connectString – 连接字符串 zk server 地址和端口"192.168.157.9:2181,192.168.157.10:2181"
         *@param sessionTimeoutMs – 会话超时时间 单位ms
         *@param connectionTimeoutMs – 连接超时时间 单位ms
         *@param retryPolicy – 重试策略
         *                   Params:
         *                   retryCount – the number of times retried so far (0 the first time)
         *                   elapsedTimeMs – the elapsed time in ms since the operation was attempted
         *                   sleeper – use this to sleep - DO NOT call Thread.sleep
         */
        //重试策略
        RetryPolicy retry = new ExponentialBackoffRetry(3000,10);
//        //1、第一种方式
//        CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.157.9:2181",
//                60 * 1000, 15 * 1000, retry);


        //2、第二种方式
        //        CuratorFrameworkFactory.Builder
         CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString("192.168.157.9:2181")
                .sessionTimeoutMs(60 * 1000)
                .connectionTimeoutMs(15 * 1000)
                .retryPolicy(retry).namespace("itheima").build();

         //你做的所有操作都认为itheima是zoorkeeper的跟目录
        //开启连接
        client.start();
    }
}

添加节点

package com.itheima.curator;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class CuratorTest {

    CuratorFramework client;

    /**
     * 创建连接
     */
    @Before
    public void testConnect(){


        /**
         *@param connectString – 连接字符串 zk server 地址和端口"192.168.157.9:2181,192.168.157.10:2181"
         *@param sessionTimeoutMs – 会话超时时间 单位ms
         *@param connectionTimeoutMs – 连接超时时间 单位ms
         *@param retryPolicy – 重试策略
         *                   Params:
         *                   retryCount – the number of times retried so far (0 the first time)
         *                   elapsedTimeMs – the elapsed time in ms since the operation was attempted
         *                   sleeper – use this to sleep - DO NOT call Thread.sleep
         */
        //重试策略
        RetryPolicy retry = new ExponentialBackoffRetry(3000,10);
//        //1、第一种方式
//        CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.157.9:2181",
//                60 * 1000, 15 * 1000, retry);


        //2、第二种方式
        //        CuratorFrameworkFactory.Builder
          client = CuratorFrameworkFactory.builder()
                .connectString("192.168.157.9:2181")
                .sessionTimeoutMs(60 * 1000)
                .connectionTimeoutMs(15 * 1000)
                .retryPolicy(retry).namespace("itheima").build();

         //你做的所有操作都认为itheima是zoorkeeper的跟目录
        //开启连接
        client.start();
    }

    /**
     * 创建节点 create 持久 临时 顺序 数据
     * 1、基本创建 create().forPath("");
     * 2、创建节点、带有数据 create().forPath("",data);
     * 3、设置节点的类型 create().withMode(CreateMode(枚举)).forPath("");
     * 4、创建多级节点 create().creatingParentsIfNeeded().forPath("/app4/p1");
     *
     *
     */
    @Test
    public void testCreate() throws Exception {
        //1、基本创建
        //如果创建节点,没有指点数据 则默认指定当前客户端的IP作为数据
        String path = client.create().forPath("/app1");
        System.out.println(path);

    }
    @Test
    public void testCreate2() throws Exception {
        //2、基本创建 带有数据的
        String path = client.create().forPath("/app2","hehe".getBytes());
        System.out.println(path);
    }
    @Test
    public void testCreate3() throws Exception {
        //3、设置节点的类型
        //默认类型:持久化
        String path = client.create().withMode(CreateMode.EPHEMERAL).forPath("/app3");
        System.out.println(path);
    }
    @Test
    public void testCreate4() throws Exception {
        //4、创建多级节点 /app1/p1
        //creatingParentsIfNeeded 如果父节点不存在 则构建父节点
        String path = client.create().creatingParentsIfNeeded().forPath("/app4/p1");
        System.out.println(path);
    }

    @After
    public void close(){
        if (client!=null){
            client.close();
        }
    }

}

查询节点

 /**
     * 查询节点
     * 1、查询数据:get: getData().forPath("")
     * 2、查询子节点: ls  getChildren().forPath("")
     * 3、查询节点状态选项 ls -s getData().storingStatIn(状态对象).getPath("")
     *
     */
    @Test
    public void testGet1() throws Exception {
        //1、查询数据:get
        byte[] path = client.getData().forPath("/app2");
        System.out.println(path);
    }

    @Test
    public void testGet2() throws Exception {
        //2、查询子节点: ls
        List<String> path = client.getChildren().forPath("/");
        System.out.println(path);
    }

    @Test
    public void testGet3() throws Exception {
        Stat status = new Stat();
        //2、查询节点的状态信息 ls -s
      client.getData().storingStatIn(status).forPath("/app1");
        System.out.println(status);
    }

修改数据

    /**
     * 修改数据
     * 1、基本修改数据 setData().forPath()
     * 2、根据版本修改 setData().withVersion().forPath()
     * version 是通过查询出来的 目的就是为了让其他客户不会干扰我 保证原子性
     */
    @Test
    public void testSet() throws Exception {
        client.setData().forPath("/app1","itcast".getBytes());
    }
    @Test
    public void testSetForVersion() throws Exception {

        Stat status = new Stat();
        //2、查询节点的状态信息 ls -s
        client.getData().storingStatIn(status).forPath("/app1");

        int version = status.getVersion(); //查询出来的
        System.out.println(version);
        client.setData().withVersion(version).forPath("/app1","haha".getBytes());

    }

删除节点

/**
     * 删除节点 delete deleteall
     * 1、删除单个节点 delete().forPath("")
     * 2、删除带有子节点的节点 delete().deletingChildrenIfNeeded().forPath("")
     * 3、必须成功的删除为了防止网络抖动 本质是重试 delete().guaranteed().forPath("");
     * 4、回调 delete().guaranteed().inBackground(方法).forPath("");
     * @throws Exception
     */
    @Test
    public void testDelete1() throws Exception {
        //1、删除单个节点
        client.delete().forPath("/app1");
    }

    @Test
    public void testDelete2() throws Exception {
        //2、删除带有子节点的节点
        client.delete().deletingChildrenIfNeeded().forPath("/app4");
    }

    @Test
    public void testDelete3() throws Exception {
        //3、必须成功的删除
        client.delete().guaranteed().forPath("/app2");
    }

    @Test
    public void testDelete4() throws Exception {
        //4、回调
        client.delete().guaranteed().inBackground(new BackgroundCallback() {
            @Override
            public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
                System.out.println("我被删除了");
                System.out.println(client);
                System.out.println(event);
            }
        }).forPath("/app1");

    }

Curator API 常用操作 - Watch事件监听

ZooKeeper 允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候, ZooKeeper服务端会将事件通知到感兴趣的客户端上去,该机制是ZooKeeper实现分布式协调服务的重要特性。

ZooKeeper中引入了Watcher机制来实现了发布/订阅功能能,能够让多个订阅者同时监听某一个对象,当一个对象自身状态变化时,会通知所有订阅者。

ZooKeeper 原生支持通过注册Watcher来进行事件监听,但是其使用并不是特别方便·需要开发人员自己反复注册Watcher,比较繁琐。

Curator引入了Cache来实现对ZooKeeper服务端事件的监听。

ZooKeeper提供了三种Watcher:

        NodeCache:只是监听某一个特定的节点

        PathChildrenCache:监控一个ZNode的子节点.

        TreeCache:可以监控整个树上的所有节点,类似于PathChildrenCache和NodeCache的组合

package com.itheima.curator;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

public class CuratorWatcherTest {

    CuratorFramework client;

    /**
     * 创建连接
     */
    @Before
    public void testConnect(){

        /**
         *@param connectString – 连接字符串 zk server 地址和端口"192.168.157.9:2181,192.168.157.10:2181"
         *@param sessionTimeoutMs – 会话超时时间 单位ms
         *@param connectionTimeoutMs – 连接超时时间 单位ms
         *@param retryPolicy – 重试策略
         *                   Params:
         *                   retryCount – the number of times retried so far (0 the first time)
         *                   elapsedTimeMs – the elapsed time in ms since the operation was attempted
         *                   sleeper – use this to sleep - DO NOT call Thread.sleep
         */
        //重试策略
        RetryPolicy retry = new ExponentialBackoffRetry(3000,10);
//        //1、第一种方式
//        CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.157.9:2181",
//                60 * 1000, 15 * 1000, retry);


        //2、第二种方式
        //        CuratorFrameworkFactory.Builder
          client = CuratorFrameworkFactory.builder()
                .connectString("192.168.157.9:2181")
                .sessionTimeoutMs(60 * 1000)
                .connectionTimeoutMs(15 * 1000)
                .retryPolicy(retry).namespace("itheima").build();

         //你做的所有操作都认为itheima是zoorkeeper的跟目录
        //开启连接
        client.start();
    }

    @After
    public void close(){
        if (client!=null){
            client.close();
        }
    }

    /**
     * 演示 NodeCache: 给指定一个节点注册监听器
     */
    @Test
    public void TestNodeCache() throws Exception {
        //1、创建NodeCache对象
        final NodeCache nodeCache = new NodeCache(client,"/app1");
        //2、注册监听
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                System.out.println("节点变化~");

                //获取修改节点后的数据
                byte[] data = nodeCache.getCurrentData().getData();
                System.out.println(data.toString());
            }
        });

        //3、开启监听 如果设置为true 则开启监听是,加载缓存数据
        nodeCache.start(true);

        while (true){

        }
    }

    /**
     * 演示 PathChildrenCache: 监听某个节点的所有子节点们
     */
    @Test
    public void testPathChildrenCache() throws Exception {
        //1、创建PathChildrenCache对象
        PathChildrenCache pc = new PathChildrenCache(client,"/app2",true);

        //2、绑定监听器
        pc.getListenable().addListener(new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent event) throws Exception {
                System.out.println("子节点变化了~");
                System.out.println(event);
                //监听子节点的数据变更,并且拿到变更后的数据

                //1、获取类型
                PathChildrenCacheEvent.Type type = event.getType();
                //2、判断类型是否是update
                if (type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)){
                    System.out.println("数据变了~");
                    byte[] data = event.getData().getData();
                    System.out.println(data.toString());
                }
            }
        });

        //3、开启
        pc.start();

        while (true){

        }
    }

    /**
     * 演示 TreeCache: 监听某个节点自己和所有子节点们
     */
    @Test
    public void treeTreeCache() throws Exception {

        //1、创建监听器
        TreeCache treeCache = new TreeCache(client, "/app2");

        //2、注册监听
        treeCache.getListenable().addListener(new TreeCacheListener() {
            @Override
            public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
                System.out.println("节点变化了~");
                System.out.println(event);
            }
        });

        //3、开启
        treeCache.start();

        while (true){

        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值