Zookeeper 学习笔记 (详细)

Zookeeper

    • 一、Zookeeper 入门
      • (1) 概述
      • (2) 特点
      • (3) 数据结构
      • (4) 应用场景
      • (5) 下载地址
    • 二、Zookeeper 安装
      • (1) 本地模式安装部署
        • ① 安装前准备
        • ② 配置修改
        • ③ 操作Zookeeper
      • (2) 配置参数解读
    • 三、Zookeeper 内部原理
      • (1) 选举机制 (★)
      • (2) 节点类型
      • (3) Stat 结构体
      • (4) 监听器原理 (★)
      • (5) 写数据流程
    • 四、Zookeeper 实战 (★)
      • 分布式安装部署
      • (1) 配置服务器编号
      • (2) 配置 zoo.cfg 文件
      • (3) 集群操作
      • 客户端命令行操作
      • (1) 启动客户端
      • (2) 显示所有操作命令
      • (3) 查看当前znode中所包含的内容
      • (4) 查看当前节点详细数据
      • (5) 分别创建2个普通节点
      • (6) 获得节点的值
      • (7) 创建短暂节点
      • (8) 创建带序号的节点
      • (9) 修改节点数据值
      • (10) 节点的值变化监听
      • (11) 节点的子节点变化监听(路径变化)
      • (12) 删除节点
      • (13) 递归删除节点
      • (14) 查看节点状态
      • API 应用
      • (1) 创建一个 maven 工程
      • (2) 添加 pom 文件
      • (3) 拷贝log4j.properties文件到项目根目录
      • (4) 创建ZooKeeper客户端
      • (5) 创建子节点
      • (6) 获取子节点并监听节点变化
      • (7) 判断Znode是否存在
      • 监听服务器节点动态上下线案例
      • (1) 需求
      • (2) 需求分析
      • (3) 具体实现
        • ① 先在集群上创建/servers节点
        • ② 服务器端向Zookeeper注册代码
        • ③ 客户端代码
        • ④ 测试
    • 五、企业面试真题


一、Zookeeper 入门

(1) 概述

Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的Apache项目。Zookeeper工作机制如下:
Zookeeper 学习笔记 (详细)_第1张图片

(2) 特点

Zookeeper 学习笔记 (详细)_第2张图片

(3) 数据结构

Zookeeper 学习笔记 (详细)_第3张图片

(4) 应用场景

提供的服务包括:统一命名服务、统一配置管理、统一集群管理、服务器节点动态上下线、软负载均衡 等。

统一命名服务
Zookeeper 学习笔记 (详细)_第4张图片
统一配置服务
Zookeeper 学习笔记 (详细)_第5张图片
统一集群管理
Zookeeper 学习笔记 (详细)_第6张图片

服务器节点动态上下线
Zookeeper 学习笔记 (详细)_第7张图片

软负载均衡
Zookeeper 学习笔记 (详细)_第8张图片

(5) 下载地址

官网


二、Zookeeper 安装

(1) 本地模式安装部署

① 安装前准备

安装Jdk
Zookeeper 学习笔记 (详细)_第9张图片

拷贝Zookeeper安装包到Linux系统下

解压:tar -zxvf 压缩包名 目录   (解压到指定目录,不加目录默认当前目录)

Zookeeper 学习笔记 (详细)_第10张图片

② 配置修改

将/opt/zookeeper-3.4.10/conf这个路径下的zoo_sample.cfg修改为zoo.cfg;

mv zoo_sample.cfg zoo.cfg

Zookeeper 学习笔记 (详细)_第11张图片

打开zoo.cfg文件,修改dataDir路径:

需要手动创建 dataDir路径
Zookeeper 学习笔记 (详细)_第12张图片

Zookeeper 学习笔记 (详细)_第13张图片

③ 操作Zookeeper

Zookeeper 学习笔记 (详细)_第14张图片

启动Zookeeper

bin/zkServer.sh start

Zookeeper 学习笔记 (详细)_第15张图片

查看进程是否启动

jps

在这里插入图片描述

查看状态:

bin/zkServer.sh status

Zookeeper 学习笔记 (详细)_第16张图片

启动客户端:

bin/zkCli.sh

Zookeeper 学习笔记 (详细)_第17张图片
在这里插入图片描述

退出客户端:

quit

Zookeeper 学习笔记 (详细)_第18张图片

停止Zookeeper

bin/zkServer.sh stop

Zookeeper 学习笔记 (详细)_第19张图片

(2) 配置参数解读

Zookeeper 学习笔记 (详细)_第20张图片


三、Zookeeper 内部原理

(1) 选举机制 (★)

Zookeeper 学习笔记 (详细)_第21张图片
Zookeeper 学习笔记 (详细)_第22张图片
Zookeeper 学习笔记 (详细)_第23张图片

(2) 节点类型

Zookeeper 学习笔记 (详细)_第24张图片

(3) Stat 结构体

Zookeeper 学习笔记 (详细)_第25张图片

(4) 监听器原理 (★)

Zookeeper 学习笔记 (详细)_第26张图片

(5) 写数据流程

Zookeeper 学习笔记 (详细)_第27张图片


四、Zookeeper 实战 (★)

分布式安装部署

在一台机器上模拟3个 zk server的集群安装

前提:解压后zookeeper后,新建三个zkData,然后在conf中将zoo_sample.cfg改名,复制三份zoo配置文件
在这里插入图片描述
Zookeeper 学习笔记 (详细)_第28张图片

(1) 配置服务器编号

在 zkData 文件夹下创建myid文件,内容分别为id值1,2,3

Zookeeper 学习笔记 (详细)_第29张图片

(2) 配置 zoo.cfg 文件

server.1=192.168.44.129:2887:3887
server.2=192.168.44.129:2888:3888
server.3=192.168.44.129:2889:3889

Zookeeper 学习笔记 (详细)_第30张图片

Zookeeper 学习笔记 (详细)_第31张图片

在这里插入图片描述

配置参数解读:server.A=B:C:D。

Zookeeper 学习笔记 (详细)_第32张图片

(3) 集群操作

分别启动Zookeeper

# 启动服务端
bin/zkServer.sh start conf/zoo1.cfg

# 启动对应服务端的客户端
bin/zkCli.sh -server localhost:2182

Zookeeper 学习笔记 (详细)_第33张图片

查看状态
( 根据之前的投票规则:正常情况下应该是 zookeeper-2 是 leader,1,3为follower )

bin/zkServer.sh status conf/zoo1.cfg 

Zookeeper 学习笔记 (详细)_第34张图片


客户端命令行操作

Zookeeper 学习笔记 (详细)_第35张图片

(1) 启动客户端

bin/zkCli.sh

bin/zkCli.sh -server localhost:2182 #指定某台server的客户端

Zookeeper 学习笔记 (详细)_第36张图片
在这里插入图片描述

(2) 显示所有操作命令

Zookeeper 学习笔记 (详细)_第37张图片

(3) 查看当前znode中所包含的内容

在这里插入图片描述

(4) 查看当前节点详细数据

Zookeeper 学习笔记 (详细)_第38张图片

(5) 分别创建2个普通节点

Zookeeper 学习笔记 (详细)_第39张图片

(6) 获得节点的值

Zookeeper 学习笔记 (详细)_第40张图片

Zookeeper 学习笔记 (详细)_第41张图片

(7) 创建短暂节点

Zookeeper 学习笔记 (详细)_第42张图片
在这里插入图片描述

(8) 创建带序号的节点

Zookeeper 学习笔记 (详细)_第43张图片

(9) 修改节点数据值

Zookeeper 学习笔记 (详细)_第44张图片

(10) 节点的值变化监听

Zookeeper 学习笔记 (详细)_第45张图片

(11) 节点的子节点变化监听(路径变化)

Zookeeper 学习笔记 (详细)_第46张图片

(12) 删除节点

Zookeeper 学习笔记 (详细)_第47张图片

(13) 递归删除节点

Zookeeper 学习笔记 (详细)_第48张图片

(14) 查看节点状态

Zookeeper 学习笔记 (详细)_第49张图片


API 应用

(1) 创建一个 maven 工程

Zookeeper 学习笔记 (详细)_第50张图片

(2) 添加 pom 文件

<dependencies>
	<dependency>
		<groupId>junitgroupId>
		<artifactId>junitartifactId>
		<version>RELEASEversion>
	dependency>
	<dependency>
		<groupId>org.apache.logging.log4jgroupId>
		<artifactId>log4j-coreartifactId>
		<version>2.8.2version>
	dependency>
	
	<dependency>
		<groupId>org.apache.zookeepergroupId>
		<artifactId>zookeeperartifactId>
		<version>3.4.10version>
	dependency>
dependencies>

(3) 拷贝log4j.properties文件到项目根目录

需要在项目的src/main/resources目录下,新建一个文件命名为“log4j.properties”,在文件中填入。
Zookeeper 学习笔记 (详细)_第51张图片

log4j.rootLogger=INFO, stdout  
log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n  
log4j.appender.logfile=org.apache.log4j.FileAppender  
log4j.appender.logfile.File=target/spring.log  
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout  
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n  

(4) 创建ZooKeeper客户端

// 创建ZooKeeper客户端,客户端连接服务端
public static void init() throws IOException {
     
    zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
     
        @Override
        public void process(WatchedEvent watchedEvent) {
     
        }
    });
}
public static void main(String[] args) throws Exception {
     
    init();
}

Zookeeper 学习笔记 (详细)_第52张图片

(5) 创建子节点

如果是远程连接操作的虚拟机中的zk,一定要记得:

关闭 linux 环境中的防火墙!
关闭 linux 环境中的防火墙!
关闭 linux 环境中的防火墙!
Zookeeper 学习笔记 (详细)_第53张图片

// 创建子节点
public static void create() throws Exception {
     

    // 参数1:要创建的节点的路径
    String path = "/testCreate";

    // 参数2:节点数据
    byte[] data = "ht".getBytes();

    // 参数3:节点权限
    List<ACL> acls = Ids.OPEN_ACL_UNSAFE;

    // 参数4:节点的类型
    CreateMode createMode = CreateMode.PERSISTENT;

    String nodeCreated = zkClient.create(path, data, acls, createMode);

    System.out.println(nodeCreated);
}
public static void main(String[] args) throws Exception {
     
    init();
    create();
}

Zookeeper 学习笔记 (详细)_第54张图片

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(6) 获取子节点并监听节点变化

获取节点

public static void getDataAndWatch() throws KeeperException, InterruptedException {
     

    List<String> children = zkClient.getChildren("/", true);

    for (String child : children) {
     
        System.out.println(child);
    }

    // 延时阻塞
    Thread.sleep(Long.MAX_VALUE);
}
// 创建ZooKeeper客户端,客户端连接服务端
public static void init() throws IOException {
     
    zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
     
        // 监听
        @Override
        public void process(WatchedEvent watchedEvent) {
     
            List<String> children = null;
            System.out.println("---------start---------");
            try {
     

                children = zkClient.getChildren("/", true);

                for (String child : children) {
     
                    System.out.println(child);
                }

            } catch (Exception e) {
     
                e.printStackTrace();
            }
            System.out.println("---------end---------");
        }
    });
}
public static void main(String[] args) throws Exception {
     
    init();
//  create();
    getDataAndWatch();
}

在这里插入图片描述
Zookeeper 学习笔记 (详细)_第55张图片

(7) 判断Znode是否存在

// 判断节点是否存在
public static void isExist() throws KeeperException, InterruptedException {
     

    Stat exists = zkClient.exists("/sanguo", false);

    System.out.println(exists==null ? "not exist" : "exist");
}
public static void main(String[] args) throws Exception {
     
    init();
//  create();
//  getDataAndWatch();
    isExist();
}

Zookeeper 学习笔记 (详细)_第56张图片


监听服务器节点动态上下线案例

(1) 需求

某分布式系统中,主节点可以有多台,可以动态上下线,任意一台客户端都能实时感知到主节点服务器的上下线

(2) 需求分析

Zookeeper 学习笔记 (详细)_第57张图片

(3) 具体实现

① 先在集群上创建/servers节点

create /servers "servers"

在这里插入图片描述

② 服务器端向Zookeeper注册代码

public class DistributeServer {
     

    private String connectString = "192.168.44.129:2181,192.168.44.129:2182,192.168.44.129:2183";
    private int sessionTimeout =  10000;
    private ZooKeeper zk = null;
    private String parentNode = "/servers";
    private static String hostname = "ht";

    public static void main(String[] args) throws Exception {
     

        DistributeServer server = new DistributeServer();

        // 服务端获取和zk的连接
        server.getConnect();

        // 注册服务器
        server.registServer(hostname);

        // 业务逻辑
        server.businesss(hostname);
    }

    // 注册服务器
    public void registServer(String hostname) throws Exception{
     

        String create = zk.create(parentNode + "/server", hostname.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);

        System.out.println(hostname +" is online "+ create);
    }


    // 业务逻辑代码
    private void businesss(String hostname) throws InterruptedException {
     

        System.out.println(hostname+" is working ...");

        // 延时阻塞
        Thread.sleep(Long.MAX_VALUE);
    }

    // 创建到zookeeper的客户端连接
    private void getConnect() throws IOException {
     

        zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
     
            @Override
            public void process(WatchedEvent watchedEvent) {
     

            }
        });
    }
    
}

③ 客户端代码

public class DistributeClient {
     
    private String connectString = "192.168.44.129:2181,192.168.44.129:2182,192.168.44.129:2183";
    private int sessionTimeout =  10000;
    private ZooKeeper zk = null;
    private String parentNode = "/servers";

    public static void main(String[] args) throws Exception {
     
        DistributeClient client = new DistributeClient();

        // 1获取zk连接
        client.getConnect();

        // 2获取servers的子节点信息,从中获取服务器信息列表
        client.getServerList();

        // 3业务进程启动
        client.business();
    }

    // 3业务进程启动
    private void business() throws InterruptedException {
     

        System.out.println("client is working ...");

        Thread.sleep(Long.MAX_VALUE);
    }

    private void getServerList() throws KeeperException, InterruptedException {
     

        // 1获取服务器子节点信息,并且对父节点进行监听
        List<String> children = zk.getChildren(parentNode, true);

        // 2存储服务器信息列表
        ArrayList<String> servers = new ArrayList<>();

        // 3遍历所有节点,获取节点中的主机名称信息
        for (String child : children) {
     

//            byte[] data = zk.getData(parentNode + "/" + child, false, null);
//
//            servers.add(new String(data));

            servers.add(child);
        }

        // 4 打印服务器列表的信息
        System.out.println(servers);
    }

    // 创建客户端和zookeeper的连接
    private void getConnect() throws IOException {
     
        zk = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
     
            @Override
            public void process(WatchedEvent watchedEvent) {
     
                // 再次启动监听
                try {
     
                    getServerList();
                } catch (Exception e) {
     
                    e.printStackTrace();
                }

            }
        });
    }

}

④ 测试

Zookeeper 学习笔记 (详细)_第58张图片
Zookeeper 学习笔记 (详细)_第59张图片


五、企业面试真题

Zookeeper 学习笔记 (详细)_第60张图片

你可能感兴趣的:(zookeeper,分布式,linux)