• ZooKeeper学习笔记


    1 概述

    • zk是基于观察者模式设计的;(观察者模式)
    • zk是一个服务管理框、协调框架;
    • zk服务本身也是一个集群,有一个leader,多个follower,类似于一主多从;
    • 集群有超过半数节点存活,zk就能对外提供服务,所以适合奇数服务器;
    • zk的一个节点默认只能存储1MB数据,所以不建议存储海量数据;
    • 一个zk集群所有节点的数据结构可以理解为一棵树;
    • zk的功能:
      • 统一命名服务:访问集群不直接通过ip,而是通过自定义的命名;
      • 统一配置管理:希望修改配置对集群内所有机器有效;
      • 统一集群管理:监控集群某个节点状态;
      • 服务节点动态上下线:节点上下线;
      • 软负载均衡:集群每个机器能力不一样,可以动态调整;

    2 安装

    可以直接安装也可以docker安装

    3 zoo.cfg配置

    • tickTime:心跳时间,zk服务端和客户端的心跳时间,单位毫秒;
    • initLimit:Leader和follower初始连接时能容忍的最多心跳数;
    • syncLimit:日常Leader和follower能容忍的最多心跳数;
    • dataDir:存储zk的数据;
    • clientPort:客户端连接的端口,默认2181,通常不做修改;

    4 zk集群配置

    • 在dataDir目录下创建myid的文件,内容为节点对应的id;
    • 在zoo.cfg新增配置:server.A=B:C:D
      • A是myid的值;
      • B是这个服务器的地址;
      • C是该服务器follower和集群Leader服务器交换信息的端口;
      • D是万一集群Leader挂了,需要一个端口重新选举,选出新的Leader;
    • 各自启动,自动选举leader和follower;

    5 客户端

    5.1 节点类型

    • 持久:客户端和服务端断开连接后,创建的节点不删除;
    • 短暂:客户端和服务端断开连接后,创建的节点自动删除;
    • 带序号:创建节点带有序号;
    • 不带序号:创建节点无序号;

    5.2 节点数据操作

    • create /my_server/server1 "192.168.0.1":my_server是集群,server1是机器名字,值为机器的ip地址;
    • get /my_server/server1:返回server1的ip地址;
    • create -e /my_server/server1 "192.168.0.1" 短暂创建;
    • set * *修改值;
    • delete /my_server/server1 :删除节点

    5.3 监听器

    利用观察者模式,zk客户端在服务端注册,如果节点数据有变化,就通知所有客户端的场景。

    • 可以监听节点数据的变化;
    • 监听子节点增删的变化;

    6 springboot客户端

    导入ZooKeeper客户端的maven依赖

    <dependency>
    	<groupId>org.apache.zookeeper</groupId>
    	<artifactId>zookeeper</artifactId>
    	<version>3.5.7</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用api

    package com.chengdugay.service;
    
    import com.alibaba.fastjson.JSON;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.zookeeper.*;
    import org.apache.zookeeper.data.Stat;
    import org.junit.Before;
    import org.junit.Test;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.io.IOException;
    import java.nio.charset.StandardCharsets;
    import java.util.List;
    
    @Slf4j
    @SpringBootTest
    public class ZKTest {
    
        /**
         * 地址
         */
        private static final String ZK_SERVER_ADDRESS = "*.*.*.*:2181";
    
        /**
         * 客户端
         */
        ZooKeeper zooKeeper;
    
        /**
         * 初始化
         *
         * @throws IOException
         */
        @Before
        public void init() throws IOException {
            zooKeeper = new ZooKeeper(ZK_SERVER_ADDRESS, 2000, new Watcher() {
                @Override
                public void process(WatchedEvent watchedEvent) {
    
                }
            });
        }
    
        @Test
        public void demo() throws InterruptedException, KeeperException {
            // 创建,返回key值
    		String s = zooKeeper.create("/server4", "192.168.1.4".getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    
            // 获取子节点变化
            List<String> children = zooKeeper.getChildren("/", true);
            log.info(JSON.toJSONString(children));
    
            // 获取节点的值
            byte[] data = zooKeeper.getData("/server1", false, zooKeeper.exists("/server1", false));
            log.info(new String(data));
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    7 服务注册与发现

    7.1 zk集群端

    创建一个分布式服务的签名create /servers "servers"

    7.2 业务服务端

    // 获取向zk注册
    zooKeeper.create("/servers/"+hostname, hostname, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
    
    // 其他业务逻辑
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    7.3 业务客户端

    // 监听zk的变化
    zooKeeper = new ZooKeeper(ZK_SERVER_ADDRESS, 2000, new Watcher() {
                @Override
                public void process(WatchedEvent watchedEvent) {
                	// 监听有服务有哪些机器的key
    				List<String> children = zooKeeper.getChildren("/servers", true);
    		        // 获取节点的值
    		        for (String child : children) {
    		            byte[] data = zooKeeper.getData("/"+child, false, null);
    		            log.info(new String(data));
    		        }
    				// 业务逻辑
                }
            });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    8 分布式锁

    原理:利用“临时顺序节点”的功能,约定只有最小序号的节点才能操作业务。
    实现:执行业务逻辑前先去zk注册“临时顺序节点”,然后获取最新的注册列表,如果就是自己刚才注册的,说明自己拿了锁,执行业务逻辑;如果没有,说明自己在排队,就需要监听,看自己什么时候能拿到锁,监听的事件就是“排在我前面的那个请求完成了他的业务逻辑”。

    9 Curator框架

    curator是一个分布锁的框架。

  • 相关阅读:
    STL再回顾(非常见知识点)
    IDEA 快捷键
    消息队列系列6-RabbitMQ使用姿势 (荣耀典藏版)
    浅学JAVA泛型一:泛型的基础知识
    Linux ALSA驱动之Platform源码分析(wm8350.c)
    基本元器件 - 二极管
    SwiftUI Swift 内功之 Swift 中的属性观察者 didSet 与 willSet
    【中秋征文】使用Python创意中秋节画月饼《花好月圆》
    iOS13之后获取状态栏高度的方法
    SSM+教学网站 毕业设计-附源码211611
  • 原文地址:https://blog.csdn.net/weixin_44215363/article/details/132383865