ZooKeeper 数据模型 Znode 结构特性详解

本文介绍了Zookeeper中的数据节点znode的结构与特性,包括节点类型(临时节点与持久化节点)、节点唯一性、路径创建规则、自动删除机制及监听机制等,并探讨了如何利用这些特性实现分布式锁等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、概述

二、节点类型

三、节点特性

四、总结


一、概述

zookeeper的数据节点可以视为树状结构(或者目录),树中的各节点被称为znode(即zookeeper node),一个znode可以有多个子节点,可以说 zookeeper 中的所有存储的数据是由 znode 组成的,并以 key/value 形式存储数据。整体结构类似于 linux 文件系统的模式以树形结构存储,其中根路径以 / 开头。

[zk: localhost:2181(CONNECTED) 0] ls /
[animal, zookeeper]
[zk: localhost:2181(CONNECTED) 2] ls /animal 
[]
[zk: localhost:2181(CONNECTED) 3] create -e -s /animal/cat "cat"
Created /animal/cat0000000002
[zk: localhost:2181(CONNECTED) 4] ls /animal                    
[cat0000000002]

 可以看到,此时存储的数据在根目录下存在 animal 和 zookeeper 两个节点,animal 节点下存在一个临时有序节点cat,大体结构如下图:

我们还可以使用如下命令获取节点的属性信息:

[zk: localhost:2181(CONNECTED) 6] get /animal
b
cZxid = 0x6
ctime = Mon Dec 14 11:03:43 CST 2020
mZxid = 0x14
mtime = Mon Dec 14 11:16:57 CST 2020
pZxid = 0x1c
cversion = 5
dataVersion = 3
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 1
numChildren = 1

下面对各个属性做一个详细的说明:

  • b:数据节点的值;
  • cZxid = 0x6:创建数据节点时的事务ID;
  • ctime = Mon Dec 14 11:03:43 CST 2020:创建数据节点时的时间;
  • mZxid = 0x14:最后一次修改数据节点时的事务ID;
  • mtime = Mon Dec 14 11:16:57 CST 2020:最后一次修改数据节点时的时间;
  • pZxid = 0x1c:表示该数据节点的子节点列表最后一次修改的事务ID,添加子节点或删除子节点就会影响子节点列表,但是修改子节点的数据内容则不影响该ID(注意,只有子节点列表变更了才会变更pzxid,子节点内容变更不会影响pzxid);
  • cversion = 5:子节点版本号(子节点的更改次数),子节点每次修改版本号加1;
  • dataVersion = 3:数据版本号(节点数据的更改次数),数据每次修改该版本号加1;
  • aclVersion = 0:权限版本号(节点的 ACL 的更改次数),权限每次修改该版本号加1;
  • ephemeralOwner = 0x0:创建该临时节点的会话的sessionID。(如果该节点是持久节点,那么这个属性值为0);
  • dataLength = 1:节点的数据长度;
  • numChildren = 1:节点拥有子节点的数量(只统计直接子节点的数量);

下面我们使用如下命令对/animal节点的值进行修改并添加一个子节点/animal/dog:

[zk: localhost:2181(CONNECTED) 8] set /animal "bb"
cZxid = 0x6
ctime = Mon Dec 14 11:03:43 CST 2020
mZxid = 0x1d
mtime = Wed Dec 16 20:25:26 CST 2020
pZxid = 0x1c
cversion = 5
dataVersion = 4
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 2
numChildren = 1
[zk: localhost:2181(CONNECTED) 9] create /animal/dog "cc"
Created /animal/dog
[zk: localhost:2181(CONNECTED) 10] get /animal
bb
cZxid = 0x6
ctime = Mon Dec 14 11:03:43 CST 2020
mZxid = 0x1d
mtime = Wed Dec 16 20:25:26 CST 2020
pZxid = 0x1e
cversion = 6
dataVersion = 4
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 2
numChildren = 2

如上可以看到,mZxid、mtime、dataVersion、numChildren、cversion都发生了变化。简单理解,可以将zookeeper类似Linux文件系统,一棵树结构,所有节点就类似树节点。

二、节点类型

zookeeper中的节点有两种,分别为临时节点和永久节点。节点的类型在创建时即被确定,并且不能改变。

  • 临时节点

该节点的生命周期依赖于创建它们的会话。一旦会话(Session)结束,临时节点将被自动删除,当然可以也可以手动删除。虽然每个临时的Znode都会绑定到一个客户端会话,但他们对所有的客户端还是可见的。另外,ZooKeeper的临时节点不允许拥有子节点。

  • 持久化节点

该节点的生命周期不依赖于会话,并且只有在客户端显示执行删除操作的时候,他们才能被删除。

三、节点特性

【a】同一级节点 key 名称是唯一的

在zookeeper中,规定同一级只能允许有一个key名称相同的文件目录,这一特性可以用来实现分布式锁。如:

[zk: localhost:2181(CONNECTED) 13] ls /animal
[cat0000000002, dog]
[zk: localhost:2181(CONNECTED) 14] create /animal/dog "dog"
Node already exists: /animal/dog     #提示/animal/dog节点已存在,无法创建节点

如上可见,当前/animal节点下面已经存在 /dog节点,再次创建会提示已经存在。

【b】创建节点时必须使用全路径

在zookeeper中,当想在某个节点下面创建子节点时,需要带上全路径。例如:

[zk: localhost:2181(CONNECTED) 17] ls /animal
[cat0000000002, dog]
[zk: localhost:2181(CONNECTED) 18] create /animal/cat cat
Created /animal/cat
[zk: localhost:2181(CONNECTED) 19] create /animal/cat/cat_1 cat_1
Created /animal/cat/cat_1
[zk: localhost:2181(CONNECTED) 20] create /animal/cat/cat_2 cat_2
Created /animal/cat/cat_2
[zk: localhost:2181(CONNECTED) 21] ls /animal/cat
[cat_1, cat_2]

如下图所示:

【c】当客户端与服务器端断开连接时,临时节点将会被删除

下面我们打开一个终端一: 创建一个临时节点,使用-e参数即可。

[zk: localhost:2181(CONNECTED) 23] ls /animal
[cat0000000002, dog, cat]
[zk: localhost:2181(CONNECTED) 24] create -e /animal/monkey monkey
Created /animal/monkey
[zk: localhost:2181(CONNECTED) 25] ls /animal                     
[monkey, cat0000000002, dog, cat]
[zk: localhost:2181(CONNECTED) 26]

打开另外一个终端二: 查看此临时节点:

[zk: localhost:2181(CONNECTING) 0] ls /animal  
[monkey, cat0000000002, dog, cat]

断开终端一与zookeeper的连接,即会话关闭:

[zk: localhost:2181(CONNECTED) 26] quit
Quitting...
2020-12-17 10:46:30,464 [myid:] - INFO  [main:ZooKeeper@693] - Session: 0x1000004fa8f0000 closed
2020-12-17 10:46:30,612 [myid:] - INFO  [main-EventThread:ClientCnxn$EventThread@522] - EventThread shut down for session: 0x1000004fa8f0000

此时,再次使用终端二重新查看此节点:

[zk: localhost:2181(CONNECTED) 1] ls /animal
[dog, cat]

我们发现,终端二已经查询不到这个临时节点了。注意同时cat0000000002节点也是临时节点来着,所以cat0000000002和monkey节点都不存在了。

【d】节点具有watch 机制,可以监听节点变化

事件监听机制类似于观察者模式,watch 监听流程是客户端向服务端某个节点路径上注册一个 watcher,同时客户端也会存储特定的 watcher,当节点数据或子节点发生变化时,服务端通知客户端,客户端进行回调处理。

特别注意:监听事件被单次触发后,事件就失效了。

【e】删除节点只能一级一级删除

如果我们删除一个存在子节点的节点,zookeeper会提示节点非空,不能删除。

[zk: localhost:2181(CONNECTED) 2] ls /animal
[dog, cat]
[zk: localhost:2181(CONNECTED) 3] delete /animal
Node not empty: /animal

不过,新版本可以通过 deleteall 命令递归删除。

四、总结

本篇文章主要总结了Zookeeper中节点znode的结构,其实我们把它类比成树的节点即可,并且总结了zookeeper节点的一些特性,通过这些特性,我们可以灵活应用到项目中的很多场景,如:

  • 分布式锁
  • 统一配置管理
  • 集群管理
  • 分布式协调/通知
  • 数据发布/订阅
  • 负载均衡
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值