Zookeeper ZK 的特性和核心概念(session/znode/acl/watch监听机制/自定义Serializer)

目录

session

数据模型

ZK 中的时间

※watch

ZK的特性

代码演示


session

https://zookeeper.apache.org/doc/r3.1.2/zookeeperStarted.html

基础概念

image.png

  • 一个客户端链接生成一个 session,由 server 生成唯一的 sessionId
  • tickTime 客户端通过tickTime(心跳时间)来保持会话
  • 当超过 会话超时时候见(ticktime * 2)未收到心跳,则认为客户端断开连接
  • 会话请求的处理按照 FIFO 进行处理

客户端连接

2020-04-12 23:36:27,418 [myid:localhost:2181] - INFO  [main-SendThread(localhost:2181):ClientCnxn$SendThread@1394] - Session establishment complete on server localhost/127.0.0.1:2181, sessionid = 0x1000584c2f70003, negotiated timeout = 30000

数据模型

image.png

层次命名空间

  • 类似unix文件系统,以(/)为根
  • 区别:节点可以包含与之关联的数据以及子节点(既是文件也是文件夹)
  • 节点的路径总是表示为规范的、绝对的、斜杠分隔的路径

Znode

概念

每一个节点被称为 znode

  • 名称唯一,命名规范
  • 节点类型:持久、顺序、临时、临时顺序
  • 节点由数据构成

节点类型

# 持久接地那
[zk: localhost:2181(CONNECTED) 15] create /gzy_01
Created /gzy_01
# 临时节点
[zk: localhost:2181(CONNECTED) 16] create -e /gzy_02
Created /gzy_02
# 顺序节点
# 1. 拥有一个 10 位的十进制序号 2. 每个父节点拥有一个计数器(各自独立)
[zk: localhost:2181(CONNECTED) 20] create /gzy_03
Created /gzy_03
[zk: localhost:2181(CONNECTED) 21] create -s /gzy_03/
Created /gzy_03/0000000000
[zk: localhost:2181(CONNECTED) 22] create -s /gzy_03/
Created /gzy_03/0000000001
[zk: localhost:2181(CONNECTED) 23] create -s /gzy_03/
Created /gzy_03/0000000002
# 临时顺序节点
[zk: localhost:2181(CONNECTED) 24] create -s -e /gzy_03/
Created /gzy_03/0000000003

数据构成

  • 存储了协调数据
  • 协调数据:节点信息、配置、位置信息等
  • 节点的元数据
  • 数据上限:1M

节点元数据

image.png

[zk: localhost:2181(CONNECTED) 35] ls -s /gzy_01
[]cZxid = 0xc
ctime = Mon Apr 13 00:02:05 CST 2020
mZxid = 0x15
mtime = Mon Apr 13 00:09:09 CST 2020
pZxid = 0xc
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0

 

ACL

https://zookeeper.apache.org/doc/r3.6.0/zookeeperProgrammers.html#sc_ZooKeeperAccessControl

  • ACLs are made up of pairs of (scheme:expression, perms).
  • For example, the pair (ip:19.22.0.0/16, READ) gives the READ permission to any clients with an IP address that starts with 19.22.

ZK 中的时间

  • Zxid
    • 每次更改操作都对应一个唯一的事务id,称为 zxid
    • 它是一个全局有序的戳记,如果 zxid1 小于 zxid2,则 zxid1 发生在 zxid2 之前。
  • Version numbers 版本号
    • 对节点的每次更改都会导致该节点的版本号之一增加。
    • 修改数据时,如果 version 小于服务器 version,则无法修改
  • Ticks
    • 当使用多服务器ZooKeeper时,服务器使用“滴答” 来定义事件的时间,如状态上传、会话超时、对等点之间的连接超时等。
    • 滴答时间仅通过最小会话超时(滴答时间的2倍)间接公开
    • 如果客户端请求的会话超时小于最小会话超时,服务器将告诉客户端会话超时实际上是最小会话超时
      • 例如使用 client 连接 server 时候,自定义了超时时间
  • Real time
    • 除了在znode创建和修改时将时间戳放入 stat 结构之外,根本不使用 Real time 或时钟时间。

※watch

  • 可以通过设置 watch,来监听 znode 的变化

image.png

监听机制

  • data watch
    • 监听节点的变化
  • child watch
    • 监听子节点的变化

触发事件

We can set watches with the three calls that read the state of ZooKeeper: exists, getData, and getChildren. The following list details the events that a watch can trigger and the calls that enable them:

  • Created event
    • Enabled with a call to exists.
  • Deleted event
    • Enabled with a call to exists, getData, and getChildren.
  • Changed event
    • Enabled with a call to exists and getData.
  • Child event 
    • Enabled with a call to getChildren.

使用时机

  • getData()
  • getChild()
  • exists()
[zk: localhost:2181(CONNECTED) 17] help
    stat path [watch]
    ls path [watch]
    ls2 path [watch]
    get path [watch]

重要特性

  • 一次有效
    • watch 被触发一次后,会立即失效
  • 顺序性
    • 客户端先得到 watch 通知,后看到 watch 结果

注意事项

  • 一次性触发器
    • 如果一个 watch 被触发后,还希望关注未来的事件,则需要重新设置 watch
  • 不可靠
    • 因为 watch 是一次性触发器,并且在获取事件和发送新的 watch 请求之间有延迟。所以不可能可靠的监听到每个节点的更改
  • 一个节点监听多个事件,只会被触发一次
    • 如果一个 watch 对象同时注册了 getData/exists,当节点被删除,删除事件对 getData/exists 都有效,但只会被调用一次

 

ZK的特性

  • 顺序一致性(Sequential Consistency)
    • 保证客户端操作是按顺序生效的。
  • 原子性(Atomicity)
    • 更新成功或失败,没有部分结果。
  • 单个系统映像
    • 无论连接到哪个服务器,客户端都将看到相同的内容。
  • 可靠性
    • 数据的变更不会丢失,除非被客户端覆盖修改。,
  • 及时性
    • 保证系统的客户端当时读取到的数据是最新的。

 

代码演示

ZkSerializer

可以定义序列化和反序列化的逻辑

public class MyZkSerializer implements ZkSerializer {

    String charset = "UTF-8";

    public Object deserialize(byte[] bytes) throws ZkMarshallingError {
        try {
            return new String(bytes, charset);
        } catch (UnsupportedEncodingException e) {
            throw new ZkMarshallingError(e);
        }
    }

    public byte[] serialize(Object obj) throws ZkMarshallingError {
        try {
            return String.valueOf(obj).getBytes(charset);
        } catch (UnsupportedEncodingException e) {
            throw new ZkMarshallingError(e);
        }
    }
}

ZkWatch

监听节点变化

public class ZkClientWatchDemo {

    static class MyDataListener implements IZkDataListener{

        @Override
        public void handleDataChange(String path, Object data) throws Exception {
            System.out.println("数据变化.path:" + path +" | data:" + data);
        }

        @Override
        public void handleDataDeleted(String s) throws Exception {
            System.out.println("节点被删除.path:" + s);
        }
    }

    public static void main(String[] args) {
        // 创建一个zk客户端
        ZkClient client = new ZkClient("localhost:2181");
        client.setZkSerializer(new MyZkSerializer());
        client.subscribeDataChanges("/gzy_01",new MyDataListener());
        System.out.println("init success.");
        try {
            Thread.sleep(1000 * 60 * 2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值