• zookeeper基础教程


    一、关于zookeeper

    Zookeeper 作为一个分布式的服务框架,主要用来解决分布式集群中应用系统的一致性问题,它能提供基于类似于文件系统的目录节点树方式的数据存储, Zookeeper 作用主要是用来维护和监控存储的数据的状态变化,通过监控这些数据状态的变化,从而达到基于数据的集群管理。

    简单的说,zookeeper=文件系统+通知机制。

    1. ZNode节点

    ZNode被分为持久(persistent)节点,顺序(sequential)节点和临时(ephemeral)节点。

    • 持久节点:即使在创建该特定znode的客户端断开连接后,持久节点仍然存在。默认情况下,除非另有说明,否则所有znode都是持久的。
    • 顺序节点:顺序节点可以是持久的或临时的。当一个新的znode被创建为一个顺序节点时,ZooKeeper通过将10位的序列号附加到原始名称来设置znode的路径。例如,如果将具有路径 /test 的znode创建为顺序节点,则ZooKeeper会将路径更改为 /test0000000001 ,并将下一个序列号设置为0000000002。如果两个顺序节点是同时创建的,那么ZooKeeper不会对每个znode使用相同的数字。顺序节点在锁定和同步中起重要作用。
    • 临时节点:客户端活跃时,临时节点就是有效的。当客户端与ZooKeeper集合断开连接时,临时节点会自动删除。因此,只有临时节点不允许有子节点。如果临时节点被删除,则下一个合适的节点将填充其位置。临时节点在leader选举中起着重要作用。

    2. Session回话

    会话对于ZooKeeper的操作非常重要。会话中的请求按FIFO顺序执行。一旦客户端连接到服务器,将建立会话并向客户端分配会话ID 

    客户端以特定的时间间隔发送心跳以保持会话有效。如果ZooKeeper集合在超过服务器开启时指定的期间(会话超时)都没有从客户端接收到心跳,则它会判定客户端死机。

    会话超时通常以毫秒为单位。当会话由于任何原因结束时,在该会话期间创建的临时节点也会被删除。

    3.Watcher监视

    监视是一种简单的机制,使客户端收到关于ZooKeeper集合中的更改的通知。客户端可以在读取特定znode时设置Watches。Watches会向注册的客户端发送任何znode(客户端注册表)更改的通知。

    Znode更改是与znode相关的数据的修改或znode的子项中的更改。只触发一次watches。如果客户端想要再次通知,则必须通过另一个读取操作来完成。当连接会话过期时,客户端将与服务器断开连接,相关的watches也将被删除。

    二、Zookeeper客户端命令

    执行bin/zkCli.sh连接zookeeper服务器后,我们随便敲一个aa然后回车,可以看到支持如下命令:

    stat path [watch] --- 查看节点状态
    set path data [version]  --- 设置节点数据
    ls path [watch]  --- 列出子节点
    delquota [-n|-b] path --- 删除节点配额
    ls2 path [watch]  --- 列出子节点,并显示当前节点信息
    setAcl path acl  --- 设置节点权限
    setquota -n|-b val path  --- 设置节点配额
    history  --- 列出历史命令
    redo cmdno  --- 执行历史命令 
    printwatches on|off
    delete path [version] --- 删除节点,如果待删除节点包含子节点则删除失败
    sync path
    listquota path  --- 列出节点配额
    get path [watch] --- 获取节点数据
    create [-s] [-e] path data acl --- 创建子节点
    addauth scheme auth  --- 增加zookeeper用户认证
    quit --- 退出zkCli
    getAcl path  --- 查询节点权限
    close --- 关闭当前连接
    connect host:port --- 连接zkServer

    1.  ls

    此命令用于列出和显示znode的子项。ls命令要求路径以/开头,并支持tab键自动补全。例如:

    • 执行:ls /                        输出[dubbo, task, zookeeper, test, disconf]: 说明根节点下包含5个子节点。
    • 执行:ls /test                 输出[test1-2, test1-1]:说明/test节点下面有2个节点。
    • 执行:ls /test/test1-2     输出[]:说明/test/test1-2节点下面没有子节点。

    2.  ls2

    此命令也用于列出和显示znode的子项,与ls命令不同的是,该命令同时列出该节点的time、version等信息。例如:

    执行 ls /test , 输出  

    [test1-2, test1-1]
    cZxid = 0x69043
    ctime = Mon Sep 03 06:37:21 CST 2018
    mZxid = 0x69043
    mtime = Mon Sep 03 06:37:21 CST 2018
    pZxid = 0x69045
    cversion = 2
    dataVersion = 0
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 3
    numChildren = 2

    3.  create

    命令格式: create [-s] [-e] path data acl

    • -s:创建顺序节点。当一个新的znode被创建为一个顺序节点时,ZooKeeper通过将10位的序列号附加到原始名称来设置znode的路径。
    • -e:创建临时节点。客户端活跃时,临时节点就是有效的。当客户端与ZooKeeper集合断开连接时,临时节点会自动删除。
    • path:待创建的节点路径。以/开头。
    • data:带创建的节点存储的数据内容。
    • acl:权限控制。后面再说。

    例如:

    • 创建永久节点:create /test/test1-3 "nodeData"
    • 创建临时节点:create -e /test/test1-4 "nodeData"
    • 创建循序节点:create -s /test/test1-5 "nodeData"

    执行完以上命令以后,再执行 ls /test,可以看到输出结果:[test1-4, test1-2, test1-3, test1-1, test1-50000000004],可以看到创建的顺序节点test1-5被增加了序列号。我们执行quit退出zkCli,再重新执行bin/zkCli.sh重新连接,执行 ls /test,输出结果:[test1-2, test1-3, test1-1, test1-50000000004],可以看到创建的临时节点test1-4已经没有了。

    4.  get

    命令格式: get path [watch]。它返回znode的关联数据和指定znode的元数据。你将获得信息,例如上次修改数据的时间,修改的位置以及数据的相关信息。

    • path:节点路径。以/开头。
    • watch:监控。后面再说。

    例如:执行 get /test/test1-3 输出

    "nodeData"
    cZxid = 0x69046
    ctime = Mon Sep 03 07:00:25 CST 2018
    mZxid = 0x69046
    mtime = Mon Sep 03 07:00:25 CST 2018
    pZxid = 0x69046
    cversion = 0
    dataVersion = 0
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 10
    numChildren = 0

    5.  set

    命令格式 set path data [version]。设置指定znode的数据。

    • path:节点路径。以/开头。
    • data:节点数据内容。
    • version: 当前数据版本号。如果该参数和当前数据版本号不一致则会抛异常。

    例如:执行 set /test/test1-3 "dataNode-New",然后我们再执行 get /test/test1-3 查看数据,输出:

    "dataNode-New"
    cZxid = 0x69046
    ctime = Mon Sep 03 07:00:25 CST 2018
    mZxid = 0x6904b
    mtime = Mon Sep 03 07:42:46 CST 2018
    pZxid = 0x69046
    cversion = 0
    dataVersion = 1
    aclVersion = 0
    ephemeralOwner = 0x0
    dataLength = 14
    numChildren = 0

    可以看到dataVersion已经发生了改变,当前 dataVersion = 1。

    6.  delete

    命令格式:delete path [version]。删除指定节点,如果要删除的节点包含子节点则会删除失败。

    • path:节点路径。以/开头。
    • version: 当前数据版本号。如果该参数和当前数据版本号不一致则会抛异常。

    例如:执行 delete /test/test1-3,再执行 ls /test,输出:[test1-2, test1-1, test1-50000000004],可以看到test1-3这个节点已经被删除掉了。

    7.  addauth

    命令格式:addauth scheme auth。该命令为zookeeper增加一个用户认证,例如:addauth digest zookeeper:zookeeper-pass。其中zookeeper为用户名,zookeeper-pass为密码。

    8.  history

    命令格式:history。该命令用来查看历史命令,查询到的历史命令前会有编号,提供redo操作。

    9.  redo

    命令格式:redo cmdno。再次执行历史命令,配合history命令使用。参数cmdno即为history命令执行结果中的编号

    三、Zookeeper权限控制

    zookeeper支持的命令中,有如下两条命令是和权限相关的:

    • setAcl path acl
    • getAcl path
    • create [-s] [-e] path data acl

    zookeeper共支持5中权限,分别是

    • create:创建节点
    • delete:删除节点
    • read:读取节点数据以及子节点
    • write:修改节点数据
    • admin:设置节点权限

    zookeeper的ACL,可以从三个维度来理解:一是scheme;二是user;三是permission。通常表示为scheme:id:permissions。

    授权模式

    • world: 表示所有,创建节点时默认此权限范围。有唯一的id是anyone。例如:setAcl /test/test1-1 world:anyone:cdrwa。表示/test/test1-1节点所有人都可以执行cdrwa操作。
    • auth:它不需要id,只要是通过认证的user都有权限。例如:setAcl /test/test1-2 auth:zookeeper:zookeeper-pass:cdrwa表示通过密码验证的用户名为zookeeper的用户可执行cdrwa操作。当然,执行此命令的前提是已经通过addauth命令添加了该用户名密码的用户。执行完setAcl命令后,再执行getAcl /test/test1-2,返回输出结果:
      'digest,'zookeeper:hdtnoeyerDQpPGLJ41lW1u1lCSA=
      : cdrwa
      请注意上面输出结果的hdtnoeyerDQpPGLJ41lW1u1lCSA=,该值紧接着我们就会用到。
    • digest:类似于auth授权。与auth授权的区别在于,输入命令的时候,用户密码需要先进行SHA-1加密再进行Base64编码。首先,先生成加密后的密码,执行:echo -n zookeeper:zookeeper-pass | openssl dgst -binary -sha1 | openssl base64,输出:hdtnoeyerDQpPGLJ41lW1u1lCSA=。可以看到该输出值即为auth授权后重新getAcl得到的值。然后,执行digest授权:setAcl /test/test1-3 digest:zookeeper:hdtnoeyerDQpPGLJ41lW1u1lCSA=:cdrwa。通过 getAcl /test/test1-3 可以看到授权结果和 getAcl /test/test1-2完全一致
    • ip:它对应的id为客户机的IP地址,设置的时候可以设置一个ip段,比如执行:setAcl /test/test1-4 ip:192.168.1.0/16:cdrwa, 表示匹配前16个bit的IP段。

     四、quota配额

    zookeeper可以在znode上设置配额限制。如果超出了配置限制,zookeeper将会在log日志中打印WARN日志。如果超出配额限制,并不会停止行为操作。

    1.  setquota

    命令格式:setquota -n|-b val path。为节点设定配额。例如命令:setquota -n 10 /test/test1-1

    • -n :限制子节点个数
    • -b :限制节点数据长度
    • val :  限制的具体的值
    • path : 要做限制的节点路径

    2.  delquota

    命令格式:delquota [-n|-b] path。删除节点配额。例如命令:delquota  -n /test/test1-1

    • -n|-b : 要删除的配额类型
    • path : 要做限制的节点路径

    3.  listquota

    命令格式:listquota path。列出节点设置的配额。例如命令:listquota  /test/test1-1

    五、zookeeper in java

    @Test
    public void testClient() throws IOException, InterruptedException, KeeperException {
        final String zookeeperHost = "10.5.31.155";
        final String zookeeperPort = "2181";
        // 链接zk服务器
        final CountDownLatch countDownLatchConnect = new CountDownLatch(1);
        final ZooKeeper zooKeeper = new ZooKeeper(zookeeperHost + ":" + zookeeperPort, 60000, event -> {
            if (event.getState().equals(Watcher.Event.KeeperState.SyncConnected)) {
                countDownLatchConnect.countDown();
            }
        });
        countDownLatchConnect.await();
    
        // watch节点 并执行创建
        zooKeeper.exists("/clientTestNode", System.out::println);
        zooKeeper.create("/clientTestNode", "clientTestNodeData".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    
        // watch节点 并执行删除
        zooKeeper.exists("/clientTestNode", System.out::println);
        zooKeeper.delete("/clientTestNode", -1);
    
        // 1. 创建节点 2. watch节点数据 3. 修改节点数据 4. 删除节点
        zooKeeper.create("/clientTestNode", "clientTestNodeData".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        byte[] dataOld = zooKeeper.getData("/clientTestNode", System.out::println, null);
        System.out.println(new String(dataOld));
        zooKeeper.setData("/clientTestNode", "clientTestNodeDataNew".getBytes(), -1);
        byte[] dataNew = zooKeeper.getData("/clientTestNode", System.out::println, null);
        System.out.println(new String(dataNew));
        zooKeeper.delete("/clientTestNode", -1);
    
        // 1. 创建节点 2. 监控节点的子节点 3. 创建子节点 4. 监控节点子节点 5. 删除子节点
        zooKeeper.create("/clientTestNode", "clientTestNodeData".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        zooKeeper.getChildren("/clientTestNode", System.out::println, null);
        zooKeeper.create("/clientTestNode/child1", "child1Data".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        zooKeeper.getChildren("/clientTestNode", System.out::println, null);
        zooKeeper.create("/clientTestNode/child2", "child2Data".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        zooKeeper.getChildren("/clientTestNode", System.out::println, null);
        zooKeeper.delete("/clientTestNode/child1", -1);
        zooKeeper.getChildren("/clientTestNode", System.out::println, null);
        zooKeeper.delete("/clientTestNode/child2", -1);
        zooKeeper.delete("/clientTestNode", -1);
    
    }

    需要注意的点:

    1. 由于zookeeper的连接是异步过程,所以执行new Zookeeper之后不要紧接着执行zookeeper命令。否则可能会出现丢失连接异常。
    2. 由于zookeeper的watcher是一次性有效(即zookeeper回调watcher后该watcher即被删除),所以会出现重复注册watcher的现象
  • 相关阅读:
    所谓的飞扬档案管理软件
    通过实例学习Virtools脚本语言VSL 解析字符串
    SQLite FAQ中文版
    通过实例学习Virtools脚本语言VSL 将物体排列于圆周上
    通过实例学习Virtools脚本语言VSL 解二次方程
    out 和 ref
    ASP.NET MVC深度接触:ASP.NET MVC请求生命周期
    ICSharpCode.SharpZipLib 压缩
    aspnet_regiis.exe 详解
    ASP.NET 配置文件 configSource 的用法
  • 原文地址:https://www.cnblogs.com/LOVE0612/p/9579751.html
Copyright © 2020-2023  润新知