11.3.3 节点属性与元数据:版本号、时间戳与ACL

本节围绕ZNode的元数据字段展开,理解版本号、时间戳与ACL的含义及其在运维与开发中的使用方式,并给出可执行示例、排错与练习。

文章图片

1. 版本号(Version)
- dataVersion:节点数据内容版本号。每次setData成功写入都会递增,用于乐观锁与并发控制。
- cversion:子节点列表版本号。每次create/delete子节点都会递增,用于监控子节点变更。
- aclVersion:ACL版本号。每次setACL更新权限都会递增,用于识别权限变更。

示例:并发写入的乐观锁

# 进入客户端(已安装ZooKeeper并启动)
/opt/zookeeper/bin/zkCli.sh -server 127.0.0.1:2181

# 创建节点
create /app/config "v1"

# 查看stat,记录dataVersion
stat /app/config
# 预期:dataVersion = 0

# 正常更新(带版本号)
set /app/config "v2" -v 0
# 预期:成功,dataVersion 变为 1

# 错误更新(旧版本)
set /app/config "v3" -v 0
# 预期:KeeperErrorCode = BadVersion

命令解释
- stat:查看元数据与版本号。
- set -v:指定写入版本号,避免并发覆盖。

2. 时间戳(Timestamp)
- ctime:节点创建时间(毫秒时间戳),用于审计与生命周期分析。
- mtime:节点最后一次数据变更时间,配合dataVersion判断更新频率。
- 时间戳由服务端生成,避免客户端时间漂移导致误判。

示例:定位异常频繁更新

# 查看节点时间戳
stat /app/config
# 输出中关注 ctime/mtime,并与运维时间线对比

3. ACL(Access Control List)
- ACL由scheme、id、perms组成,定义谁可以以何种方式访问节点。
- 常见scheme:world(所有人)、auth(已认证用户)、digest(用户名密码摘要)、ip(IP限制)。
- 常用权限:r读、w写、c创建子节点、d删除子节点、a管理权限。

示例:创建带digest权限的节点

# 进入客户端
/opt/zookeeper/bin/zkCli.sh -server 127.0.0.1:2181

# 添加认证(用户名/密码)
addauth digest admin:Admin@123

# 创建带权限节点
create /secure/app "secret" digest:admin:$(echo -n "admin:Admin@123" | openssl dgst -binary -sha1 | openssl base64):rwca

# 查看ACL
getAcl /secure/app
# 预期:显示 digest 方案与 rwca 权限

命令解释
- addauth:为当前会话添加认证。
- getAcl:查看当前节点ACL。

4. 安装与环境准备(示例环境)

# 下载安装(示例路径)
tar -zxvf apache-zookeeper-3.8.4-bin.tar.gz -C /opt
ln -s /opt/apache-zookeeper-3.8.4-bin /opt/zookeeper

# 基础配置
cp /opt/zookeeper/conf/zoo_sample.cfg /opt/zookeeper/conf/zoo.cfg
sed -i 's@dataDir=/tmp/zookeeper@dataDir=/data/zookeeper@' /opt/zookeeper/conf/zoo.cfg

# 启动
/opt/zookeeper/bin/zkServer.sh start
/opt/zookeeper/bin/zkServer.sh status

5. 运维与排错要点
- BadVersion:说明并发写入冲突,使用stat获取最新dataVersion或重试。
- NoAuth:权限不足,检查addauth或ACL是否生效,核对aclVersion是否递增。
- 权限变更未生效:确认setAcl是否成功,检查客户端是否仍使用旧会话。

排错示例

# 查看版本号与ACL是否更新
stat /secure/app
getAcl /secure/app

# 重新设置ACL并验证
setAcl /secure/app world:anyone:r
getAcl /secure/app

6. 练习
1. 创建/app/lock节点,记录dataVersion,模拟两次并发set,观察BadVersion错误。
2. 对/secure/app设置world:anyone:r后,使用未认证会话读取并验证权限。
3. 观察ctime/mtimesetData变化,记录时间差异并解释原因。