zookeeper

zookeeper

Zookeeper介绍

见zookeeper原理.md

Zookeeper作用?
Zookeeper是一个高效的分布式协调服务,可以提供配置信息管理、命名、分布式同步、集群管理、数据库切换等服务。它不适合用来存储大量信息,可以用来存储一些配置、发布与订阅等少量信息。

Zookeeper应用场景:
Hadoop、Storm、消息中间件、RPC服务框架、分布式数据库同步系统都需要依赖Zookeeper做信息同步

简介:

​ 客户端发起事务请求,事务请求的结果在整个Zookeeper集群中所有机器上的应用情况是一致的。不会出现集群中部分机器应用了该事务,而存在另外一部分集群中机器没有应用该事务的情况。
​ 在Zookeeper集群中的任何一台机器,其看到的服务器的数据模型是一致的。Zookeeper能够保证客户端请求的顺序,每个请求分配一个全局唯一的递增编号,用来反映事务操作的先后顺序。Zookeeper将全量数据保存在内存中,并直接服务于所有的非事务请求,在以读操作为主的场景中性能非常突出。

Zookeeper中的进程:
Zookeeper集群中的节点,根据其身份特性分为leader、follower、observer。leader负责客户端writer类型的请求;follower负责客户端reader类型的请求,并参与leader选举;observer是特殊的follower,可以接收客户端reader请求,但是不会参与选举,可以用来扩容系统支撑能力,提高读取速度

Zookeeper是一个基于观察者模式设计的分布式服务管理框架,负责存储和管理相关数据,接收观察者的注册。一旦这些数据的状态发生变化,zookeeper就负责通知那些已经在zookeeper集群进行注册并关心这些状态发生变化的观察者,以便观察者执行相关操作。

zookeeper的集群安装

在master虚拟机

1.上传jar包并解压

tar -zxvf  apache-zookeeper-3.5.7-bin.tar.gz

2.重命名解压文件夹

mv apache-zookeeper-3.5.7-bin zookeeper-3.5.7

3.配置

(1)重命名zoo_sample.cfg

mv zoo_sample.cfg zoo.cfg

(2)修改zoo.cfg

vim zoo.cfg

修改dataDir为

dataDir=/usr/local/soft/zookeeper-3.5.7/data

(结束修改要创建该目录)

在最后面加上

server.0=master:2888:3888
server.1=node1:2888:3888
server.2=node2:2888:3888

(3)进入/usr/local/soft/zookeeper-3.5.7/data目录下

创建文件myid

vim myid

输入文件内容为0(对应上面的server.0)

(4)将安装目录分发到node1和node2中

scp -r zookeeper-3.5.7 node1:`pwd`

scp -r zookeeper-3.5.7 node2:`pwd`

(5)到node1和node2修改myid,将0分别改为1和2

(6)配置环境变量,每个虚拟机都要

 vim /etc/profile

最后一行加上:

export ZOOKEEPER_HOME=/usr/local/soft/zookeeper-3.5.7
export PATH=$ZOOKEEPER_HOME/bin:$PATH

使其生效

source /etc/profile

(7)启动并查看状态(每个都需要)

zkServer.sh start 
zkServer.sh status

Zookeeper命令(客户端操作)

查看路径下的节点
ls path
创建节点
create 节点 --> 创建普通节点
create 节点 节点数据 --> 创建普通节点并携带数据
create -s 节点 --> 创建节点并在节点名称后添加编号
create -e 节点 --> 创建临时节点
获取节点中的数据
get 节点
get -s 节点 查看节点中的数据并获取详细状态信息
get -w 节点 表示监听某个节点中的变化(只会触发一次效果)

设置节点中的数据
set 节点 数据 --> 给节点重新赋予数据
获取节点状态信息
stat 节点
删除节点
delete 节点 – 可以删除一个不为空的节点(没有子节点)
deleteall 节点
退出客户端
quit

在/usr/local/soft/zookeeper-3.5.7目录下

zkCli.sh

当看到如下输出信息时,表示已经成功连接上本地的ZooKeeper服务器了:

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

上面的命令没有显式地指定ZooKeeper服务器地址,默认是连接本地的ZooKeeper服务器。如果希望连接指定的ZooKeeper服务器,可以通过如下方式实现:

zkCli.sh -server ip:port

例如:

 zkCli.sh -server node1:2181

查看路径下的节点
ls path

ls /

在这里插入图片描述

创建节点
create 节点 --> 创建普通节点

create /shell

在这里插入图片描述

create /shell/node1

create /shell/node2

ls /shell

在这里插入图片描述

create 节点 节点数据 --> 创建普通节点并携带数据

create /shell/node1/next_node1 "node1 value"

获取节点中的数据
get 节点

get /shell/node1/next_node1

在这里插入图片描述

create -s 节点 --> 创建节点并在节点名称后添加编号

create -s /shell/node1

在这里插入图片描述

create -e 节点 --> 创建临时节点

create -e /shell/node3

作用:关闭了zookeeper节点重启就没有了

get -s 节点 查看节点中的数据并获取详细状态信息

get -s /shell/node1/next_node1

在这里插入图片描述

set 节点 数据 --> 给节点重新赋予数据

set /shell/node1/next_node1 "nodes value"

get -w 节点 表示监听某个节点中的变化(只会触发一次效果)

get -w /shell/node1/next_node1

在这里插入图片描述

Zookeeper的API使用

添加Pom依赖:

````
<dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.5.7</version>
</dependency>
````

实现功能:
①创建永久节点或临时节点
②获取节点数据
③获取当前节点的子节点
④监听节点变化
⑤删除节点

连接zookeeper

package com.shujia;

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

import java.io.IOException;

public class Code01ZookeeperCon {
    public static void main(String[] args) throws IOException, InterruptedException {

        String connection = "master:2181,node1:2181,node2:2181";
        int sessionTimeoutm = 1000 * 20;
        /**
         *  sessionTimeoutm  session timeout in milliseconds
         *  会话超时时间,毫秒为单位
         *
         *  Watcher watcher 表示一个观察者,可以观察当前连接的状态  该Watcher是一个接口
         *      需要使用匿名内部类方式创建其对象,并实现其process方法 当连接发生变化时,就会执行process中定义的逻辑
         *
         */
        ZooKeeper zooKeeper = new ZooKeeper(connection, sessionTimeoutm, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                System.out.println("当前连接发生变化...");
            }
        });

        System.out.println("当前行被执行..");
        zooKeeper.close();

        /*
            执行结果:
                当前行被执行..
                当前连接发生变化...
                当前连接发生变化...
           当前行被执行 -> 当zooKeeper对象被创建后,就可以往下执行
           1.当前连接发生变化 -> zooKeeper连接是异步发生的 创建好连接 会执行
           2.当前连接发生变化 -> 连接被关闭时,连接发生变化 也会被执行
         */

    }
}


API操作

package com.shujia;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.List;

import static com.oracle.jrockit.jfr.ContentType.Bytes;

public class Code02ZookeeperAPI {
    ZooKeeper zooKeeper = null;

    @Before
    public void getCon() throws IOException {

        String connection = "master:2181";
        int sessionTimeoutm = 1000 * 30;
        zooKeeper = new ZooKeeper(connection, sessionTimeoutm, new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                System.out.println("当前连接发生变化...");
            }
        });

    }


    @Test
    public void createNode() throws InterruptedException, KeeperException {
        /**
         *  public String create(final String path, byte data[], List<ACL> acl,
         *             CreateMode createMode)
         *         throws KeeperException, InterruptedException
         *  ZooDefs.Ids.OPEN_ACL_UNSAFE 可以返回List<ACL> 对应是对节点基于所有权限
         *
         *  CreateMode
         *      PERSISTENT:持久化节点 普通节点 会一直存在
         *      EPHEMERAL:临时节点 当连接被关闭,创建的节点会消失
         *      PERSISTENT_WITH_TTL: 带有生命周期节点
         *
         */
        String path = "/api";
        String data = "create api";

        zooKeeper.create(path, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

    }

    @Test
    public void createEphemeralNode() throws InterruptedException, KeeperException {
        /**
         * 对于临时节点,当会话连接关闭后,当前节点就会消失
         */
        zooKeeper.create("/api/ephemeralNode", "ephemeral Node".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        Thread.sleep(10 * 1000);
    }


    /*
        获取节点数据
     */
    @Test
    public void getNodeData() throws InterruptedException, KeeperException {
        /*
            public byte[] getData(String path, boolean watch, Stat stat)
            watch 参数就相当于 get -w 命令
            Stat stat 应该是当前路径的节点对应的状态信息

            如果查看节点数据,要求节点必须先存在
         */

        String path = "/api";
        // 结果为stat 那么如何判断是否存在?
        //  如果路径不存在,那么返回结果为null
        Stat stat = zooKeeper.exists(path, false);

        if (stat != null) {
            byte[] bytes = zooKeeper.getData(path, false, stat);
            String nodeData = new String(bytes);
            System.out.println(nodeData);
        }

//        zooKeeper.getData(path,false,)

    }

    //获取当前节点的子节点
    @Test
    public void getChild() throws InterruptedException, KeeperException {
//        List<String> children = zooKeeper.getChildren("/api", false);
//        for (String child : children) {
//            System.out.println(child);
//        }
        // 遍历节点及子节点
        getAllChild("/api");
    }


    public void getAllChild(String path) throws InterruptedException, KeeperException {
        List<String> children = zooKeeper.getChildren(path, false);
        if (children.size() > 0) {
            for (String child : children) {
                System.out.println("获取到子节点:" + path + "/" + child);
                getAllChild(path + "/" + child);
            }
        }
    }

//   监听节点变化

    @Test
    public void getChange() throws InterruptedException, KeeperException {
        byte[] data = zooKeeper.getData("/api", new Watcher() {
                    @Override
                    public void process(WatchedEvent event) {
                        try {
                            Thread.sleep(10 * 1000);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                        System.out.println("当前节点发生变化...");

                    }
                }, zooKeeper.exists("/api", false)
        );
        System.out.println(new String(data));

    }


    @Test
    public void deleteNode() throws InterruptedException, KeeperException {
        // -1 表示不指定具体版本 删除最新节点
//        zooKeeper.delete("/api/node1/next_node1",-1);
        // KeeperErrorCode = Directory not empty for /api
        zooKeeper.delete("/api",-1);

        // 递归迭代删除当前节点下所有节点 -- 小作业自己完成
    }

    @After
    public void close() throws InterruptedException {
        zooKeeper.close();
    }
}

基于Zookeeper构建HA

HDFS的HA,指的是在一个集群中存在两个NameNode,分别运行在独立的物理节点上。在任何时间点,只有一个NameNodes是处于Active状态,另一种是在Standby状态。 Active NameNode负责所有的客户端的操作,而Standby NameNode用来同步Active NameNode的状态信息,以提供快速的故障恢复能力。
为了保证Active NN与Standby NN节点状态同步,即元数据保持一致。除了DataNode需要向两个NN发送block位置信息外,还构建了一组独立的守护进程”JournalNodes”,用来同步Edits信息。当Active NN执行任何有关命名空间的修改,它需要持久化到一半以上的JournalNodes上。而Standby NN负责观察JNs的变化,读取从Active NN发送过来的Edits信息,并更新自己内部的命名空间。一旦ActiveNN遇到错误,Standby NN需要保证从JNs中读出了全部的Edits,然后切换成Active状态。
使用HA的时候,不能启动SecondaryNameNode,会出错。

两个NameNode,分别运行在独立的物理节点上。在任何时间点,只有一个NameNodes是处于Active状态,另一种是在Standby状态。 Active NameNode负责所有的客户端的操作,而Standby NameNode用来同步Active NameNode的状态信息,以提供快速的故障恢复能力。
为了保证Active NN与Standby NN节点状态同步,即元数据保持一致。除了DataNode需要向两个NN发送block位置信息外,还构建了一组独立的守护进程”JournalNodes”,用来同步Edits信息。当Active NN执行任何有关命名空间的修改,它需要持久化到一半以上的JournalNodes上。而Standby NN负责观察JNs的变化,读取从Active NN发送过来的Edits信息,并更新自己内部的命名空间。一旦ActiveNN遇到错误,Standby NN需要保证从JNs中读出了全部的Edits,然后切换成Active状态。
使用HA的时候,不能启动SecondaryNameNode,会出错。

详见HA步骤.md

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值