zookeeper安装与基本使用

zookeeper安装与基本使用

概念

基本概念

zookeeper 是apache 提供了一个开源的分布式协调服务框架。zookeeper可以从设计模式的角度理解为观察者模式设计的分布式服务管理框架。它被当作一个服务信息的注册中心,注册者对它进行信息的注册,然后接受观察,一旦注册的服务发生改变,就把更新推送给观察者。因此可以把它理解为:zookeeper=文件系统+通知机制。

特点

1.一个领导者leader和多个跟随者follower组成的工作集群。

2.全局数据一致,zookeeper中集群各个节点存储的数据信息相同,每个服务节点server保存的都是相同的数据副本。

3.数据更新原子性,数据更新是一个原子性操作,要么所有节点都更新成功,要么都更新失败。

4.更新请求顺序执行,来自同一个客户端 client的更新请求按其发送顺序依次执行

5.数据实时性,在一定时间范围内,客户端client能读取到最新的数据

6.leader 负责进行投票的发起和决议,更新系统状态。

7.follower可以同 leader一样,用于接收客户端请求并向客户端返回结果(相同数据副本),在选举leader过程中参与投票

8.zookeeper 集群中只要有半数以上节点存活,zookeeper 集群就可正常对外提供服务。

9.zookeeper 集群的数据发生更新时,主动推送给观察zookeeper 集群的观察者数据发生了改变。

数据结构

zookeeper 底层数据存储数据采用了 树 的数据结构,与 unix 文件系统存储文件的结构类似。zookeeper 树中的每个节点被称为 znode ,znode 用来存储和唯一标识数据,znode 默认存储 1M 数据。访问 znode 相对于访问唯一标识的路径。

img
zookeeper应用场景
服务节点动态上下线

hadoop HA 中 双 namenode 或 双 resourcemanger 的配置,通过zookeeper 作为服务节点的注册中心,自动感知节点的信息健康状况,节点挂掉后,zookeeper 通知hadoop 集群,自动实现了节点的转换,保证了hadoop集群的高可用。

img

RPC 框架dubbo 中,zookeeper 根据本身得分特性,作为服务注册中心,负责保存 dubbo 服务的元数据信息,并可以基于长连接通知观察者服务的上下线。

image-20200729090249211
统一命名服务

img
统一配置管理

img
统一集群管理

img
软负载均衡

img
数据发布订阅

img
总的来说,zookeeper 的应用场景基本都是符合其特性的,集群数据同步(各节点数据信息一致)和数据更新时自动向观察zookeeper 集群的观察者推送更新。

安装部署

下载地址:https://zookeeper.apache.org/releases.html
单机部署
安装zookeeper 需要依赖于 java 环境,JDK 环境安装前面已经提及多变,这里不再赘述
利用xshell解压上传 zookeeper 压缩包到用户家目录

image-20200915191200844
解压修改文件权限
# 解压文件
sudo tar -xzvf zookeeper-3.4.10.tar.gz -C /opt/module
# 文件重命名
sudo mv zookeeper-3.4.0.tar.gz zookeeper
# 修改文件权限
sudo chown -R hadoop ./zookeeper
修改配置文件

配置文件在 zookeeper 安装目录的 conf 目录下

重命名 zoo_sample.cfg 为 zoo.cfg

mv zoo_sample.cfg zoo.cfg

修改编辑 zoo.cfg 文件为

# 主要修改 zookeeper 数据存放的位置
dataDir=/opt/module/zookeeper/zkdata
clientPort=2181
创建存放数据文件
mkdir /opt/module/zookeeper/zkdata
修改环境变量
sudo vim /etc/profile

添加如下配置

##ZOOKEEPER_HOME
export ZOOKEEPER_HOME=/opt/module/zookeeper
export PATH=$PATH:$ZOOKEEPER_HOME/bin
export PATH=$PATH:$ZOOKEEPER_HOME/conf

环境变量生效

source /etc/profile
启动zookeeper 查看状态
# 启动 zookeeper 服务
zkServer.sh start
# 查看 zookeeper 进程信息
jps   # 结果会有 jps  QuorumPeerMain 两个进程
# 查看zookeeper 服务状态
zkServer.sh status #  显示结果为 Mode: standalone
# 进入 zookeeper 客户端  quit  推出客户端进程
zkCli.sh
# 查看 zookeeper 版本号
echo stat|nc localhost 2181
伪分布式部署

伪分布式部署的本质时在本地配置三个不同的配置文件,根据配置文件中配置的数据和日志存放位置不同,端口号不同来进行模仿分布式效果。实际上就是本地启动多个不同端口号,相互之间存在联系通信的zookeeper 进程

相同上传修改文件,配置环境变量这里就不在赘述,同上面一样
在zookeeper 安装目录下创建三个zoo1.cfg、zoo2.cfg、zoo3.cfg文件
cd /opt/module/zookeeper/conf
# 创建三个配置文件
touch zoo{1..3}.cfg
修改zoo1.cng 到 zoo3.cnf

zoo1.cnf

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/opt/module/zookeeper/zkdata1
dataLogDir=/opt/module/zookeeper/zkdata1
clientPort=2181
# node1 需要在 /etc/hosts 中配置 ip 与主机之间的映射
server.1=node1:20881:30881
server.2=node1:20882:30882
server.3=node1:20883:30883

zoo2.cnf

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/opt/module/zookeeper/zkdata2
dataLogDir=/opt/module/zookeeper/zkdata2
clientPort=2182
# node1 需要在 /etc/hosts 中配置 ip 与主机之间的映射
server.1=node1:20881:30881
server.2=node1:20882:30882
server.3=node1:20883:30883

zoo3.cnf

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/opt/module/zookeeper/zkdata3
dataLogDir=/opt/module/zookeeper/zkdata3
clientPort=2183
# node1 需要在 /etc/hosts 中配置 ip 与主机之间的映射
server.1=node1:20881:30881
server.2=node1:20882:30882
server.3=node1:20883:30883
分别为每个配置文件创建zkdata目录
mkdir /opt/module/zookeeper/zkdata{1..3}
在每个zkdata文件下创建 myid 文件(名称与zoo.cnf中 server后的编号对应,代表 zookepper 应用在 zookeeper集群中的编号)
# 三个文件都要配置,这里以 zkdata1 为例
cd /opt/module/zookeeper/zkdata1 
touch myid
echo  1 > myid # 具体以实际编号为例
cat myid
启动伪分布式集群
# 启动不同的 zookeeper进程
zkServer.sh start conf/zoo1.cfg
zkServer.sh start conf/zoo1.cfg
zkServer.sh start conf/zoo1.cfg
# 查看 zookeeper 服务状态
zkServer.sh status conf/zoo1.cfg
zkServer.sh status conf/zoo2.cfg
zkServer.sh status conf/zoo3.cfg
分布式部署
zooker 集群部署最低需要三台机器,这里以三台机器为例
集群规划
sudo vim /etc/hosts

添加符合实际情况的主机与ip映射

image-20200915201503680
上传 zookeeper 压缩包到 hadoop131 家目录,并进行解压赋予权限
sudo tar -xzvf zookeeper.tar.gz -C /opt/module
sudo chown -R hadoop:hadoop ./zookeeper

image-20200915201830696
重命名 zookeeper 安装目录下的 conf 目录下的zoo_sample.cfg为zoo.cfg
mv /opt/module/zookeeper/conf/zoo_sample.cfg /opt/module/zookeeper/conf/zoo.cfg
配置conf 目录下zoo.cfg文件如下

image-20200915202259139
配置conf 目录下文件如下log4j.properties文件

image-20200915202447958
zookeeper安装目录下创建 zkdata
mkdir ./zookeeper/zkdata
# 创建日志记录文件
mkdir ./zookeeper/zkdata/logs
配置编辑服务器编号
touch ./zookeeper/zkdata/myid
echo 1 > ./zookeeper/zkdata/myid # 与服务器编号保持一致
修改 zookeeper安装目录 bin 下的zkEnv.sh(修改日志记录位置)

image-20200915203001345
集群分发 zookeeper
scp -r /opt/module/zookeepe root@hadoop132:/opt/module/
scp -r /opt/module/zookeepe root@hadoop133:/opt/module/
修改分发机器的 myid
# 修改 hadoop132 机器与zookeeper 中配置的zookeeper 编号保持一致
echo 2 > /opt/module/zookeeper/zkdata/myid
# 修改 hadoop133 机器与zookeeper 中配置的zookeeper 编号保持一致
echo 3 > /opt/module/zookeeper/zkdata/myid
分别在每台机器上配置 zookeeper 环境变量(同上一样)
分别在每台机器上启动zookeeper(前提配置环境变量)
zkServer.sh start
分别在每台机器上查看 zookeeper 进程和状态
zkServer.sh status
jps

image-20200915204304410

zookeeper 操作

命令操作
启动客户端
zkCli.sh

image-20200915204649309
API 操作
统一maven pom依赖
<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.8.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.11</version>
        </dependency>
    </dependencies>
zookeeper 基本 API 操作

test 类

package com.ldy.zk;

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;

public class Testzk {
    // 集群可以多个节点通过 , 进行并列(连接)
    private static String connect="192.168.0.115:2181";
    private static int sessionTimeout=2000;
    private ZooKeeper zkclient;

    //构造zookeeper客户端
    @Before
    public void init() throws IOException {
      zkclient=new ZooKeeper(connect, sessionTimeout, new Watcher() {
          public void process(WatchedEvent watchedEvent) {
              // 收到事件通知后的回调函数(用户的业务逻辑)
              System.out.println(watchedEvent.getType() + "--" + watchedEvent.getPath());
              // 再次启动监听
              try {
                  zkclient.getChildren("/", true);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      });
    }

    //判断节点是否存在
    @Test
    public void exist() throws KeeperException, InterruptedException {
        Stat exists = zkclient.exists("/hbase", false);
        System.out.println(exists==null ? "不存在" : "存在");
    }

    //创建节点
    @Test
    public void create() throws KeeperException, InterruptedException {
        // 参数1:要创建的节点的路径; 参数2:节点数据 ; 参数3:节点权限 ;参数4:节点的类型
        String nodeCreated = zkclient.create("/atguigu", "jinlian".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    }

    @Test
    //获取子节点并监听节点变化
    public void getchilds() throws KeeperException, InterruptedException {
        List<String> children = zkclient.getChildren("/", true);
        for(String child:children){
            System.out.println(child);
        }
        //延时阻塞
        Thread.sleep(Long.MAX_VALUE);
    }


    @After
    //关闭连接
    public void close() throws InterruptedException {
        if(zkclient!=null){
            zkclient.close();
            System.out.println("释放连接资源");
        }
        else return;
    }

}
zookeeper 监听服务上下线实例

Client 类

package com.ldy.zk;

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

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

public class Client {
    private String connectUrl="master:2181";
    private int sessionTimeout=2000;
    //连接需要释放资源
    private ZooKeeper zkClient;

    //获取连接
    public void getconnect() throws IOException {
        zkClient=new ZooKeeper(connectUrl, sessionTimeout, new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                try {
                    getchilds();
                } catch (KeeperException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }
    //监听节点上下线
    public void getchilds() throws KeeperException, InterruptedException {
        List<String> children = zkClient.getChildren("/servers", true);
        List<String> list=new ArrayList<String>();
        for (String child : children) {
            byte[] data = zkClient.getData("/servers/" + child, false, null);
            list.add(new String(data));
        }
        System.out.println("------上线节点信息-----");
        for (String s : list) {
            System.out.println(s+"已经上线");
        }
    }

    //业务处理代码
    public void process() throws InterruptedException {
        Thread.sleep(Long.MAX_VALUE);
    }

    public static void main(String[] args) throws Exception {
        Client client=new Client();
    //获取连接
        client.getconnect();
    //监听节点上下线
        client.getchilds();
    //业务处理
        client.process();
    }
}

ResigstServer 类

package com.ldy.zk;

import org.apache.zookeeper.*;

import java.io.IOException;

import static java.lang.Long.MAX_VALUE;

public class ResigstServer {
   private String connectUrl="master:2181";
   private int sessionTimeout=2000;
   //连接需要释放资源
   private ZooKeeper zkClient;

   //获取zookeeper连接
    public void getconnect() throws IOException {
        zkClient=new ZooKeeper(connectUrl, sessionTimeout, new Watcher() {
            public void process(WatchedEvent watchedEvent) {
            }
        });
    }

    //注册服务
    public void registserver(String hostname) throws KeeperException, InterruptedException {
        // 创建一个  znode 节点
        String path = zkClient.create("/servers/server", hostname.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        System.out.println("-----------------");
        System.out.println(hostname+"节点已经上线");
    }

    //业务处理
    public void process() throws InterruptedException {
        Thread.sleep(Long.MAX_VALUE);
    }


    public static void main(String[] args) throws Exception {
        //获取zookeeper连接
        ResigstServer resigstServer=new ResigstServer();
        resigstServer.getconnect();
        //注册服务
        resigstServer.registserver(args[0]);
        //业务处理
        resigstServer.process();
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值