Zookeeper入门介绍

发布时间 2023-04-25 07:45:47作者: wuxin001

放本地文件夹都快吃土了,准备清理文件夹,关于Zookeeper的!

介绍

核心概念

zookeeper是一个分布式的开源框架,它能很好的管理集群,而且提供协调分布式应用的基本服务。

它向外部应用暴露一组通用服务——分布式同步(Distributed Synchronization)、命名服务(Naming Service)、集群维护(Group Maintenance)等,简化分布式应用协调及其管理的难度,提供高性能的分布式服务。

zookeeper本身可以以standalone模式(单节点状态)安装运行,不过它的长处在于通过分布式zookeeper集群(一个leader,多个follower),基于一定的策略来保证zookeeper集群的稳定性和可用性,从而实现分布式应用的可靠性。

集群角色介绍

zookeeper集群中主要有两个角色:leader和follower。

领导者(leader),用于负责进行投票的发起和决议,更新系统状态。

学习者(learner),包括跟随者(follower)和观察者(observer)。

其中follower用于接受客户端请求并想客户端返回结果,在选主过程中参与投票。

而observer可以接受客户端连接,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了扩展系统,提高读取速度。

zookeeper节点部署的越多,服务的可靠性也就越高。当然建议最好是部署奇数个,偶数个不是不可以。但是zookeeper集群是以宕机个数过半才会让整个集群宕机的,所以奇数个集群更佳。

docker安装

安装

# 1、拉取 zookeeper 镜像
docker pull zookeeper:3.7.1-temurin

# 2、创建 zookeeper 配置文件目录 用于挂载
mkdir -p /usr/local/zookeeper/conf
echo  "tickTime=2000
dataDir=/var/lib/zookeeper 
clientPort=2181" \
>>/usr/local/zookeeper/conf/zoo.cfg


# 3、启动 zookeeper
docker run --name zookeeper01 --restart always -d \
-p 2181:2181 \
-v /usr/local/zookeeper/conf/zoo.cfg:/conf/zoo.cfg zookeeper:3.7.1-temurin
docker run --name zookeeper01 --restart always -d \
-v /usr/local/zookeeper/conf/zoo.cfg:/conf/zoo.cfg zookeeper:3.7.1-temurin
docker run --name zookeeper01 --restart always -d  zookeeper:3.7.1-temurin

操作

# 进入容器
root@8b57a494c9e5:/apache-zookeeper-3.7.1-bin# ls

# 启动 zookeeper
bin/zkServer.sh start

# 进入zookeeper
bin/zkCli.sh -server 127.0.0.1:2181

成功进入后看到如下界面

Welcome to ZooKeeper!
JLine support is enabled
... # 中间具体内容省略
[zk: localhost:2181(CONNECTED) 0] 

命令

可以参考 : https://zookeeper.net.cn/zookeeperCLI.html

成功进入后使用help查勘zookeeper全部命令


        addauth scheme auth     			 ### 节点添加权限
        close                                            ### 节点添加权限
        config [-c] [-w] [-s]                            ### 配置文件
        connect host:port                                ### 连接
        create [-s] [-e] [-c] [-t ttl] path [data] [acl] ### 添加节点
        delete [-v version] path 		         ### 根据节点版本号删除节点
        deleteall path [-b batch size]                   ### 删除该节点以及该节点所有子节点
        delquota [-n|-b|-N|-B] path
        get [-s] [-w] path                               ### 获取节点内容
        getAcl [-s] path                                 ### 获取一条路径的ACL权限
        getAllChildrenNumber path                        ### 获取特定路径下的所有子节点数
        getEphemerals path
        history                                          ### 查看操作历史
        listquota path                                   ### 列出一个路径的配额
        ls [-s] [-w] [-R] path
        printwatches on|off                              ### 打开/关闭是否打印手表的开关。
        quit                                             ### 退出
        reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
        redo cmdno
        removewatches path [-c|-d|-a] [-l]
        set [-s] [-v version] path data                  ### 设置节点内容 
        setAcl [-s] [-v version] [-R] path acl
        setquota -n|-b|-N|-B val path
        stat [-w] path
        sync path                                        ### 异步操作节点
        version                                          ### 查看zookeeper版本信息
        whoami                                 	  	 ### 查看用户信息

基本操作实例

添加节点

# 创建节点
create /zk_test1

# 设置节点内容
set /zk_test1 zk_test1_content

# 获取节点详细内容
get -s /zk_test1
### 测试 添加 给/zk_test1节点添加两个
zk: localhost:2181(CONNECTED) 20] create /zk_test1/zk_test1_child1
Created /zk_test1/zk_test1_child1
[zk: localhost:2181(CONNECTED) 21] create /zk_test1/zk_test1_child2
Created /zk_test1/zk_test1_child2
[zk: localhost:2181(CONNECTED) 22] set /zk_test1/zk_test1_child1 zk_test1_child1_content
[zk: localhost:2181(CONNECTED) 23] set /zk_test1/zk_test1_child2 zk_test2_child2_content
[zk: localhost:2181(CONNECTED) 24] ls -R /
/
/zk_test1
/zk_test2
/zookeeper
/zk_test1/zk_test1_child1
/zk_test1/zk_test1_child2
/zookeeper/config
/zookeeper/quota
[zk: localhost:2181(CONNECTED) 25] 

删除命令

[zk: localhost:2181(CONNECTED) 25] delete /zk_test2
[zk: localhost:2181(CONNECTED) 26] delete /zk_test1
Node not empty: /zk_test1

因为节点 /zk_test1含有子节点 ,直接是删除不掉的 需要使用 deleteall 命令,这里就不测试了

版本号测试

[zk: localhost:2181(CONNECTED) 30] get -s /zk_test1/zk_test1_child1
zk_test1_child1_content
cZxid = 0xb
ctime = Thu Sep 01 19:38:41 UTC 2022
mZxid = 0xd
mtime = Thu Sep 01 19:39:12 UTC 2022
pZxid = 0xb
cversion = 0
dataVersion = 1   ### 第一次内容版本号
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 23
numChildren = 0
[zk: localhost:2181(CONNECTED) 31] set /zk_test1/zk_test1_child1 content_change_child1
[zk: localhost:2181(CONNECTED) 32] get -s /zk_test1/zk_test1_child1
content_change_child1
cZxid = 0xb
ctime = Thu Sep 01 19:38:41 UTC 2022
mZxid = 0x11
mtime = Thu Sep 01 19:47:33 UTC 2022
pZxid = 0xb
cversion = 0
dataVersion = 2   ### 内容修改之后版本号
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 21
numChildren = 0

根据版本号删除节点

[zk: localhost:2181(CONNECTED) 33] delete -v 1  /zk_test1/zk_test1_child1
version No is not valid : /zk_test1/zk_test1_child1
[zk: localhost:2181(CONNECTED) 34] delete -v 2  /zk_test1/zk_test1_child1
[zk: localhost:2181(CONNECTED) 35] get  /zk_test1/zk_test1_child1
Node does not exist: /zk_test1/zk_test1_child1 ### 成功删除节点了!

设置权限

[zk: localhost:2181(CONNECTED) 44] addauth digest user1:12345
[zk: localhost:2181(CONNECTED) 46] create /acl_auth_test 
Created /acl_auth_test
[zk: localhost:2181(CONNECTED) 47] setAcl /acl_auth_test auth:user1:12345:crwad
[zk: localhost:2181(CONNECTED) 48] getAcl /acl_auth_test
'digest,'user1:+owfoSBn/am19roBPzR1/MfCblE=

重新开个窗口进入容器

docker exec -it zookeeper01 /bin/bash
bin/zkCli.sh -server 127.0.0.1:2181
WatchedEvent state:SyncConnected type:None path:null
[zk: 127.0.0.1:2181(CONNECTED) 0] getAcl /acl_auth_test
Insufficient permission : /acl_auth_test

此时无权限获取节点 /acl_auth_test 内容

设置一个节点权限

setAcl -R /acl_auth_test auth:user1:12345:crwad

其他命令

[zk: localhost:2181(CONNECTED) 67] whoami
Auth scheme: User
ip: 127.0.0.1
digest: user1
[zk: localhost:2181(CONNECTED) 68] version
ZooKeeper CLI version: 3.7.1-a2fb57c55f8e59cdd76c34b357ad5181df1258d5, built on 2022-05-07 06:45 UTC

节点属性

cZxid 创建节点时的事务ID
ctime 创建节点时的时间
mZxid 最后修改节点时的事务ID
mtime 最后修改节点时的时间
pZxid 表示该节点的子节点列表最后一次修改的事务ID,添加子节点或删除子节点就会影响子节点列表,但是修改子节点的数据内容则不影响该ID(注意,只有子节点列表变更了才会变更pzxid,子节点内容变更不会影响pzxid)
cversion 子节点版本号,子节点每次修改版本号加1
dataversion 数据版本号,数据每次修改该版本号加1
aclversion 权限版本号,权限每次修改该版本号加1
ephemeralOwner 创建该临时节点的会话的sessionID。 * 如果该节点是持久节点,那么这个属性值为0)*
dataLength 该节点的数据长度
numChildren 该节点拥有子节点的数量(只统计直接子节点的数量)

Zookeeper的应用场景

    1. 数据发布/订阅
    1. 负载均衡
    1. 分布式协调/通知
    1. 集群管理
    1. 集群管理
    1. master 管理
    1. 分布式锁
    1. 分布式队列

代码操作

开启服务

首先开启一个docker容器

docker run -d --restart=always -p 2181:2181 --name=zookeeper02 zookeeper:3.7.1-temurin

客户端的zookeeper原生 API

测试连接 这个容器

ConnectionDemo

 public static void main(String[] args) throws Exception {
        try {
            final CountDownLatch countDownLatch = new CountDownLatch(1);
            ZooKeeper zooKeeper =
                    new ZooKeeper("192.168.56.40:2181",

                            4000, new Watcher() {
                        @Override
                        public void process(WatchedEvent event) {
                            if (Event.KeeperState.SyncConnected == event.getState()) {
                                //如果收到了服务端的响应事件,连接成功
                                countDownLatch.countDown();
                            }
                        }
                    });
            countDownLatch.await();
            //CONNECTED
            System.out.println(zooKeeper.getState());

            // 添加一个节点
            createNode(zooKeeper,"/zk_testNode1","创建第一个节点");

        } catch (Exception e) {
            System.err.println(e.toString());
        }
    }

    public static void createNode(ZooKeeper zooKeeper, String path, String message) {
        try {
            zooKeeper.create(path, message.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        } catch (KeeperException | InterruptedException e) {
            e.printStackTrace();
        }
    }

控制台输出结果,出现 CONNECTED 说明连接成功

D:\environment\java\jdk\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:3677,suspend=y,server=n -javaagent:C:\Users\Administrator\AppData\Local\JetBrains\IntelliJIdea2021.2\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "D:\environment\java\jdk\jre\lib\charsets.jar;D:\environment\java\jdk\jre\lib\deploy.jar;D:\environment\java\jdk\jre\lib\ext\access-bridge-64.jar;D:\environment\java\jdk\jre\lib\ext\cldrdata.jar;D:\environment\java\jdk\jre\lib\ext\dnsns.jar;D:\environment\java\jdk\jre\lib\ext\jaccess.jar;D:\environment\java\jdk\jre\lib\ext\jfxrt.jar;D:\environment\java\jdk\jre\lib\ext\localedata.jar;D:\environment\java\jdk\jre\lib\ext\nashorn.jar;D:\environment\java\jdk\jre\lib\ext\sunec.jar;D:\environment\java\jdk\jre\lib\ext\sunjce_provider.jar;D:\environment\java\jdk\jre\lib\ext\sunmscapi.jar;D:\environment\java\jdk\jre\lib\ext\sunpkcs11.jar;D:\environment\java\jdk\jre\lib\ext\zipfs.jar;D:\environment\java\jdk\jre\lib\javaws.jar;D:\environment\java\jdk\jre\lib\jce.jar;D:\environment\java\jdk\jre\lib\jfr.jar;D:\environment\java\jdk\jre\lib\jfxswt.jar;D:\environment\java\jdk\jre\lib\jsse.jar;D:\environment\java\jdk\jre\lib\management-agent.jar;D:\environment\java\jdk\jre\lib\plugin.jar;D:\environment\java\jdk\jre\lib\resources.jar;D:\environment\java\jdk\jre\lib\rt.jar;D:\desktop\Learn\admin\zookeeper\target\classes;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\zookeeper\zookeeper\3.7.1\zookeeper-3.7.1.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\zookeeper\zookeeper-jute\3.7.1\zookeeper-jute-3.7.1.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\yetus\audience-annotations\0.12.0\audience-annotations-0.12.0.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-handler\4.1.76.Final\netty-handler-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-common\4.1.76.Final\netty-common-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-resolver\4.1.76.Final\netty-resolver-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-buffer\4.1.76.Final\netty-buffer-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-transport\4.1.76.Final\netty-transport-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-codec\4.1.76.Final\netty-codec-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-transport-native-epoll\4.1.76.Final\netty-transport-native-epoll-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-transport-native-unix-common\4.1.76.Final\netty-transport-native-unix-common-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-transport-classes-epoll\4.1.76.Final\netty-transport-classes-epoll-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\slf4j\slf4j-api\1.7.35\slf4j-api-1.7.35.jar;D:\software\idea\IntelliJ IDEA 2021.2\lib\idea_rt.jar" com.wuxin.zookeeper.ConnectionDemo
Connected to the target VM, address: '127.0.0.1:3677', transport: 'socket'
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
SLF4J: Failed to load class "org.slf4j.impl.StaticMDCBinder".
SLF4J: Defaulting to no-operation MDCAdapter implementation.
SLF4J: See http://www.slf4j.org/codes.html#no_static_mdc_binder for further details.
CONNECTED
Disconnected from the target VM, address: '127.0.0.1:3677', transport: 'socket'

进入容器查看添加节点

# 进入容器
docker exec -it zookeeper02 /bin/bash
# 连接zookeeper服务
bin/zkCli.sh -server 127.0.0.1:2181

#查看内容
[zk: 127.0.0.1:2181(CONNECTED) 0] ls /
[zk_testNode1, zookeeper]

节点添加成功!

其他操作类似

客户端的curator连接

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;


public class CuratorDemo {
    public static void main(String[] args) throws Exception {
        CuratorFramework curatorFramework =
                CuratorFrameworkFactory
                        .builder()
                        .connectString("192.168.56.40:2181")
                        .sessionTimeoutMs(4000).retryPolicy(new ExponentialBackoffRetry(1000, 3)).
                        namespace("").build();
        curatorFramework.start();
        Stat stat = new Stat();
        //查询节点数据
        byte[] bytes = curatorFramework.getData().storingStatIn(stat).forPath("/zk_testNode1");
        System.out.println(new String(bytes));
        curatorFramework.close();
    }
}

输出内容,可以看到输出内容获取到

D:\environment\java\jdk\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:3824,suspend=y,server=n -javaagent:C:\Users\Administrator\AppData\Local\JetBrains\IntelliJIdea2021.2\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "D:\environment\java\jdk\jre\lib\charsets.jar;D:\environment\java\jdk\jre\lib\deploy.jar;D:\environment\java\jdk\jre\lib\ext\access-bridge-64.jar;D:\environment\java\jdk\jre\lib\ext\cldrdata.jar;D:\environment\java\jdk\jre\lib\ext\dnsns.jar;D:\environment\java\jdk\jre\lib\ext\jaccess.jar;D:\environment\java\jdk\jre\lib\ext\jfxrt.jar;D:\environment\java\jdk\jre\lib\ext\localedata.jar;D:\environment\java\jdk\jre\lib\ext\nashorn.jar;D:\environment\java\jdk\jre\lib\ext\sunec.jar;D:\environment\java\jdk\jre\lib\ext\sunjce_provider.jar;D:\environment\java\jdk\jre\lib\ext\sunmscapi.jar;D:\environment\java\jdk\jre\lib\ext\sunpkcs11.jar;D:\environment\java\jdk\jre\lib\ext\zipfs.jar;D:\environment\java\jdk\jre\lib\javaws.jar;D:\environment\java\jdk\jre\lib\jce.jar;D:\environment\java\jdk\jre\lib\jfr.jar;D:\environment\java\jdk\jre\lib\jfxswt.jar;D:\environment\java\jdk\jre\lib\jsse.jar;D:\environment\java\jdk\jre\lib\management-agent.jar;D:\environment\java\jdk\jre\lib\plugin.jar;D:\environment\java\jdk\jre\lib\resources.jar;D:\environment\java\jdk\jre\lib\rt.jar;D:\desktop\Learn\admin\zookeeper\target\classes;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\zookeeper\zookeeper\3.7.1\zookeeper-3.7.1.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\zookeeper\zookeeper-jute\3.7.1\zookeeper-jute-3.7.1.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\yetus\audience-annotations\0.12.0\audience-annotations-0.12.0.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-handler\4.1.76.Final\netty-handler-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-common\4.1.76.Final\netty-common-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-resolver\4.1.76.Final\netty-resolver-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-buffer\4.1.76.Final\netty-buffer-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-transport\4.1.76.Final\netty-transport-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-codec\4.1.76.Final\netty-codec-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-transport-native-epoll\4.1.76.Final\netty-transport-native-epoll-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-transport-native-unix-common\4.1.76.Final\netty-transport-native-unix-common-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-transport-classes-epoll\4.1.76.Final\netty-transport-classes-epoll-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\slf4j\slf4j-api\1.7.35\slf4j-api-1.7.35.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\curator\curator-framework\4.0.0\curator-framework-4.0.0.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\curator\curator-client\4.0.0\curator-client-4.0.0.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\com\google\guava\guava\20.0\guava-20.0.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\curator\curator-recipes\4.0.0\curator-recipes-4.0.0.jar;D:\software\idea\IntelliJ IDEA 2021.2\lib\idea_rt.jar" com.wuxin.zookeeper.CuratorDemo
Connected to the target VM, address: '127.0.0.1:3824', transport: 'socket'
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
SLF4J: Failed to load class "org.slf4j.impl.StaticMDCBinder".
SLF4J: Defaulting to no-operation MDCAdapter implementation.
SLF4J: See http://www.slf4j.org/codes.html#no_static_mdc_binder for further details.
创建第一个节点

监听


import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;

public class WatcherDemo implements Watcher {
    static ZooKeeper zooKeeper;

    static {
        try {
            // 连接客户端
            zooKeeper = new ZooKeeper("192.168.56.40:2181", 4000, new WatcherDemo());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void process(WatchedEvent event) {
        System.out.println("eventType:" + event.getType());
        if (event.getType() == Event.EventType.NodeDataChanged) {
            try {
                zooKeeper.exists(event.getPath(), true);
            } catch (KeeperException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
        String path = "/watcher";
        if (zooKeeper.exists(path, false) == null) {
            zooKeeper.create("/watcher", "0".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }
        Thread.sleep(1000);
        System.out.println("-----------");
        //true表示使用zookeeper实例中配置的watcher
        Stat stat = zooKeeper.exists(path, true);
        System.in.read();
    }
}

控制台内容

D:\environment\java\jdk\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:14799,suspend=y,server=n -javaagent:C:\Users\Administrator\AppData\Local\JetBrains\IntelliJIdea2021.2\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 -classpath "D:\environment\java\jdk\jre\lib\charsets.jar;D:\environment\java\jdk\jre\lib\deploy.jar;D:\environment\java\jdk\jre\lib\ext\access-bridge-64.jar;D:\environment\java\jdk\jre\lib\ext\cldrdata.jar;D:\environment\java\jdk\jre\lib\ext\dnsns.jar;D:\environment\java\jdk\jre\lib\ext\jaccess.jar;D:\environment\java\jdk\jre\lib\ext\jfxrt.jar;D:\environment\java\jdk\jre\lib\ext\localedata.jar;D:\environment\java\jdk\jre\lib\ext\nashorn.jar;D:\environment\java\jdk\jre\lib\ext\sunec.jar;D:\environment\java\jdk\jre\lib\ext\sunjce_provider.jar;D:\environment\java\jdk\jre\lib\ext\sunmscapi.jar;D:\environment\java\jdk\jre\lib\ext\sunpkcs11.jar;D:\environment\java\jdk\jre\lib\ext\zipfs.jar;D:\environment\java\jdk\jre\lib\javaws.jar;D:\environment\java\jdk\jre\lib\jce.jar;D:\environment\java\jdk\jre\lib\jfr.jar;D:\environment\java\jdk\jre\lib\jfxswt.jar;D:\environment\java\jdk\jre\lib\jsse.jar;D:\environment\java\jdk\jre\lib\management-agent.jar;D:\environment\java\jdk\jre\lib\plugin.jar;D:\environment\java\jdk\jre\lib\resources.jar;D:\environment\java\jdk\jre\lib\rt.jar;D:\desktop\Learn\admin\zookeeper\target\classes;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\zookeeper\zookeeper\3.7.1\zookeeper-3.7.1.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\zookeeper\zookeeper-jute\3.7.1\zookeeper-jute-3.7.1.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\yetus\audience-annotations\0.12.0\audience-annotations-0.12.0.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-handler\4.1.76.Final\netty-handler-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-common\4.1.76.Final\netty-common-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-resolver\4.1.76.Final\netty-resolver-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-buffer\4.1.76.Final\netty-buffer-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-transport\4.1.76.Final\netty-transport-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-codec\4.1.76.Final\netty-codec-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-transport-native-epoll\4.1.76.Final\netty-transport-native-epoll-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-transport-native-unix-common\4.1.76.Final\netty-transport-native-unix-common-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\io\netty\netty-transport-classes-epoll\4.1.76.Final\netty-transport-classes-epoll-4.1.76.Final.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\slf4j\slf4j-api\1.7.35\slf4j-api-1.7.35.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\curator\curator-framework\4.0.0\curator-framework-4.0.0.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\curator\curator-client\4.0.0\curator-client-4.0.0.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\com\google\guava\guava\20.0\guava-20.0.jar;D:\environment\java\maven\apache-maven-3.8.3\maven-repo\org\apache\curator\curator-recipes\4.0.0\curator-recipes-4.0.0.jar;D:\software\idea\IntelliJ IDEA 2021.2\lib\idea_rt.jar" com.wuxin.zookeeper.WatcherDemo
Connected to the target VM, address: '127.0.0.1:14799', transport: 'socket'
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
SLF4J: Failed to load class "org.slf4j.impl.StaticMDCBinder".
SLF4J: Defaulting to no-operation MDCAdapter implementation.
SLF4J: See http://www.slf4j.org/codes.html#no_static_mdc_binder for further details.
eventType:None

监听之后在 docker 容器中操作节点 /watcher 操作,

set /watcher watcher_content

控制台新增内容,监听到了节点发生了变化。

-----------
eventType:NodeDataChanged

部分源代码

# 设置监控 
request.setWatch(watcher != null);

zookeeper集群搭建

docker 容器下 zookeeper 目录如下

root@8b57a494c9e5:/# ls
apache-zookeeper-3.7.1-bin  data                  etc    lib64   mnt   run   tmp
bin                         datalog               home   libx32  opt   sbin  usr
boot                        dev                   lib    logs    proc  srv   var
conf                        docker-entrypoint.sh  lib32  media   root  sys
root@8b57a494c9e5:/# 

配置文件和 id文件分别在 confdata 配置文件中

修改配置文件 /conf/zoo.cfg

dataDir=/data
dataLogDir=/datalog
tickTime=2000
initLimit=5
syncLimit=2
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
standaloneEnabled=true
admin.enableServer=true
server.1=localhost:2888:3888;2181

主要添加以下内容

server.1=192.168.56.10:2888:3888;2181
server.2=192.168.56.20:2888:3888;2181
server.3=192.168.56.30:2888:3888;2181

其他三个类似,然后就是修改 /data/myid 内容依次为 1 、2 、3

修改完毕之后需要重新启,这三台就可以默认为是一个zookeeper小集群了

详细内容可以参考

ZAB协议

zookeeper 原子广播协议 https://zookeeper.net.cn/zookeeperInternals.html#sc_consistency

ZooKeeper 的核心是一个原子消息系统,它使所有服务器保持同步。

Zookeeper原理

监听机制

选举算法

分布式锁