《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/xuan_lu/article/details/107675047 「null」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

首先说明一下环境,溪源使用zookeeper版本为3.5.10;由于版本不同,命令语法略有差异,提前说明一下,但是基本原理一致,大家可以通过help命令查看自己当前版本的命令语法。

客户端、服务器命令

切换至zookeeper安装目录下的bin目录输入以下命令启动服务器或者客户端
1. 启动ZK服务: ./zkServer.sh start
2. 查看ZK服务状态: ./zkServer.sh status
3. 停止ZK服务: ./zkServer.sh stop
4. 重启ZK服务: ./zkServer.sh restart
5. 连接内部客户端: ./zkCli.sh或者./zkCli.sh -server 127.0.0.1(指定连接服务器IP):2181

节点属性

学习zookeeper常用命令之前先介绍一下节点属性的含义。

-`cZxid`:当前数据结点创建时的事务ID——针对于`zookeeper`数据结点的管理:我们对结点数据的一些写操作都会导致`zookeeper`自动地为我们去开启一个事务,并且自动地去为每一个事务维护一个事务`ID`
- `ctime`:当前数据结点创建时的时间
- `mZxid`:当前数据结点最后一次更新时的事务ID
- `mtime`:当前数据结点最后一次更新时的时间
- `pZxid`:当前数据节点最后一次修改**其**子节点**更改的`zxid`。修改指(增加子节点、删除子节点),并不指其子节点的数据发生改变;
- `cversion`:当前数据节点对应**子结点**的更改次数
- `dataVersion`:当前结点数据的发生更改的次数
- `aclVersion`:当前结点的ACL更改次数——类似`linux`的权限列表,维护的是当前结点的权限列表被修改的次数
- `ephemeralOwner`:如果结点是临时结点,则表示创建该结点的会话的`SessionID`;如果是持久结点,该属性值为0
- `dataLength`:当前节点的数据内容长度
- `numChildren`:当前数据结点的子结点个数

help命令

zookeeper基本常用命令通过help查看,遇到错误命令可以直接查询语法。

ZooKeeper -server host:port cmd args
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
delquota [-n|-b] path
get [-s] [-w] path
getAcl [-s] path
history
listquota path
ls [-s] [-w] [-R] path
ls2 path [watch]
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]
rmr path
set [-s] [-v version] path data
setAcl [-s] [-v version] [-R] path acl
setquota -n|-b val path
stat [-w] path
sync path
Command not found: Command not found help

新增、查询节点

  • 新增命令:create [-s] [-e] path data
    其中 -s 为有序结点,-e 临时结点(默认是持久结点)
  • 查询命令:get [-s] [-w] path
    -s 查看节点所有信息:数据信息+节点属性值
    -w 查看节点数据信息
  • 实战
//创建持久化节点node1
[zk: localhost:2181(CONNECTED) 0] create /node1 "123"
Created /node1
//查看node1节点属性
[zk: localhost:2181(CONNECTED) 1] get -s /node1
123
cZxid = 0x43
ctime = Wed Jul 29 21:27:31 CST 2020
mZxid = 0x43
mtime = Wed Jul 29 21:27:31 CST 2020
pZxid = 0x43
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
//创建有序持久化节点
[zk: localhost:2181(CONNECTED) 2] create -s /seqNode1 "seq1"
Created /seqNode10000000011
//查看有序持久化节点信息
[zk: localhost:2181(CONNECTED) 3] get -s /seqNode10000000011
seq1
cZxid = 0x44
ctime = Wed Jul 29 21:28:25 CST 2020
mZxid = 0x44
mtime = Wed Jul 29 21:28:25 CST 2020
pZxid = 0x44
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
//创建临时节点
[zk: localhost:2181(CONNECTED) 4] create -s -e /tmpNode1 "tmp"
Created /tmpNode10000000012
[zk: localhost:2181(CONNECTED) 5] get -s /tmpNode10000000012
tmp
cZxid = 0x45
ctime = Wed Jul 29 21:35:28 CST 2020
mZxid = 0x45
mtime = Wed Jul 29 21:35:28 CST 2020
pZxid = 0x45
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x10029ab39130008
dataLength = 3
numChildren = 0

修改节点

  • 命令: set [-s] [-v version] path data
    可以直接进行修改;也可以选择使用版本号
    -v + 版本号,类似乐观锁原理;
[zk: localhost:2181(CONNECTED) 13] set /node1 "456"
[zk: localhost:2181(CONNECTED) 14] get -w /node1
456
[zk: localhost:2181(CONNECTED) 15] set -v 0 /node1 "234"

WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/node1
[zk: localhost:2181(CONNECTED) 16] get -w /node1
234

删除节点

  • 命令:

delete [-v version] path:可以直接删除,也可以指定版本号删除,此命令只能删除单个节点,如果存在子节点,则需要依次删除子节点

deleteall path:直接删除指定的所有节点

[zk: localhost:2181(CONNECTED) 0] delete /node1
[zk: localhost:2181(CONNECTED) 1] get -s /node1
org.apache.zookeeper.KeeperException$NoNodeException: KeeperErrorCode = NoNode for /node1
[zk: localhost:2181(CONNECTED) 4] create /node1 "node1"
Created /node1
[zk: localhost:2181(CONNECTED) 5] create /node1/node11 "node11"
Created /node1/node11
//使用delete删除存在子节点的节点,删除失败
[zk: localhost:2181(CONNECTED) 6] delete /node1
Node not empty: /node1
[zk: localhost:2181(CONNECTED) 7] get -s /node1
node1
cZxid = 0x4f
ctime = Wed Jul 29 21:53:37 CST 2020
mZxid = 0x4f
mtime = Wed Jul 29 21:53:37 CST 2020
pZxid = 0x50
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 1
[zk: localhost:2181(CONNECTED) 8] deleteall /node1
[zk: localhost:2181(CONNECTED) 9] get /node1
org.apache.zookeeper.KeeperException$NoNodeException: KeeperErrorCode = NoNode for /node1

注意:删除存在子节点时,命令不要再使用rmr,此命令已经无效。

[zk: localhost:2181(CONNECTED) 17] rmr /node1
The command 'rmr' has been deprecated. Please use 'deleteall' instead.

查看子节点列表

  • 命令:

ls [-s] [-w] [-R] path:

ls2 path [watch]

[zk: localhost:2181(CONNECTED) 19] ls /
[a0000000001, b0000000002, c, hadoop, seqNode10000000011, zookeeper]
[zk: localhost:2181(CONNECTED) 20] ls -s /
[a0000000001, b0000000002, c, hadoop, seqNode10000000011, zookeeper]cZxid = 0x0
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x0
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x53
cversion = 22
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 6

[zk: localhost:2181(CONNECTED) 21] create /node1 "node1"
Created /node1
//当前节点下没有子节点,返回空数组
[zk: localhost:2181(CONNECTED) 22] ls /node1
[]
[zk: localhost:2181(CONNECTED) 23] create /node1/node11 "node11"
Created /node1/node11
[zk: localhost:2181(CONNECTED) 24] ls /node1
[node11]

查看节点状态

使用stat命令查看节点状态,与get命令的区别是此命令不返回数据信息;

[zk: localhost:2181(CONNECTED) 25] stat /node1
cZxid = 0x55
ctime = Wed Jul 29 22:05:16 CST 2020
mZxid = 0x55
mtime = Wed Jul 29 22:05:16 CST 2020
pZxid = 0x56
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 1

监听器

特殊说明get path [watch]命令已被废弃:

[zk: localhost:2181(CONNECTED) 27] get /node1 watch
'get path [watch]' has been deprecated. Please use 'get [-s] [-w] path' instead.
node1

使用 get [-s] [-w] path注册的监听器能够在结点内容发生改变的时候,向客户端发出通知。需要注意的是zookeeper的触发器是一次性的(One-time trigger),即触发一次后就会立即失效。

//一个窗口监听,新打开一个窗口修改节点数据
[zk: localhost:2181(CONNECTED) 29] get -w /node1
node1
//收到修改信息
[zk: localhost:2181(CONNECTED) 30]
WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/node1

//另一个窗口修改节点:
[zk: localhost:2181(CONNECTED) 0] set /node1 "set node1"

权限控制

zookeeper类似文件系统,client可以创建结点、更新结点、删除结点,那么如何做到结点的权限控制呢?
zookeeperaccess control list 访问控制列表可以做到这一点。
acl权限控制,使用scheme:id:permission来标识,主要涵盖3个方面:

  1. 权限模式(scheme):授权的策略

  2. 授权对象(id):授权的对象

  3. 权限(permission):授予的权限
    权限模式

    | 方案 | 描述 |

    | --- | --- |
    

    | world | 只有一个用户:anyone,代表登录zookeeper所有人(默认) |
    | ip | 对客户端使用IP地址认证 |
    | auth | 使用已添加认证的用户认证 |
    | digest | 使用”用户名:密码”方式认证 |

授权对象

  • 给谁授予权限
  • 授权对象ID是指,权限赋予的实体,例如:IP地址或用户

权限

  • create、delete、read、writer、admin也就是 增、删、查、改、管理权限,这5种权限简写为 c d r w a,注意:
    这五种权限中,有的权限并不是对结点自身操作的例如:delete是指对子结点的删除权限。
    可以试图删除父结点,但是子结点必须删除干净,所以delete的权限也是很有用的
权限 ACL简写 描述
create c 可以创建子结点
delete d 可以删除子结点(仅下一级结点)
read r 可以读取结点数据以及显示子结点列表
write w 可以设置结点数据
admin a 可以设置结点访问控制权限列表

授权的相关命令

命令 使用方式 描述
getAcl getAcl 读取ACL权限
setAcl setAcl 设置ACL权限
addauth addauth 添加认证用户
  • world模式:
[zk: localhost:2181(CONNECTED) 31] getAcl /node1
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 32] setAcl /node1 world:anyone:drwa
[zk: localhost:2181(CONNECTED) 33] create /node1/node2 "node2"
Authentication is not valid : /node1/node2
[zk: localhost:2181(CONNECTED) 34] setAcl /node1 world:anyone:cdrwa
[zk: localhost:2181(CONNECTED) 35] create /node1/node2 "node2"
Created /node1/node2
  • IP模式:
    需要两台虚拟机一起授权的话需要用逗号将授权列表隔开:setAcl /ipNode ip:192.168.103.133:cdrwa,ip:192.168.103.132:cdrwa
[zk: localhost:2181(CONNECTED) 8] create /ipNode "ipNode"
Created /ipNode
[zk: localhost:2181(CONNECTED) 9] get -s /ipNode
ipNode
cZxid = 0x65
ctime = Wed Jul 29 23:22:23 CST 2020
mZxid = 0x65
mtime = Wed Jul 29 23:22:23 CST 2020
pZxid = 0x65
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
[zk: localhost:2181(CONNECTED) 10] setAcl /ipNode ip:192.168.16.81:ra
[zk: localhost:2181(CONNECTED) 11] get -s /ipNode
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /ipNode
  • auth模式:
    命令:
    addauth digest <user>:<password>
    setAcl <path> auth:<user>:<acl>
//认证用户
[zk: localhost:2181(CONNECTED) 36] addauth digest qxy:123456
[zk: localhost:2181(CONNECTED) 37] get -s /node1
set node1
cZxid = 0x55
ctime = Wed Jul 29 22:05:16 CST 2020
mZxid = 0x58
mtime = Wed Jul 29 22:31:29 CST 2020
pZxid = 0x5c
cversion = 2
dataVersion = 1
aclVersion = 2
ephemeralOwner = 0x0
dataLength = 9
numChildren = 2
//设置认证用户
[zk: localhost:2181(CONNECTED) 38] setAcl /node1 auth:qxy:cdrwa
//退出,重新进入
[zk: localhost:2181(CONNECTED) 39] quit

WATCHER::

WatchedEvent state:Closed type:None path:null
2020-07-29 22:58:56,574 [myid:] - INFO [main:ZooKeeper@1422] - Session: 0x10029ab39130009 closed
2020-07-29 22:58:56,574 [myid:] - INFO [main-EventThread:ClientCnxn$EventThread@524] - EventThread shut down for session: 0x10029ab39130009
//未用户认证,无法获取节点信息
[zk: localhost:2181(CONNECTED) 0] get -s /node1
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /node1
//认证用户,注意此处密码错误,不会提示错误,但是无法访问节点
[zk: localhost:2181(CONNECTED) 1] addauth digest qxy:123456
[zk: localhost:2181(CONNECTED) 2] get -s /node1
set node1
cZxid = 0x55
ctime = Wed Jul 29 22:05:16 CST 2020
mZxid = 0x58
mtime = Wed Jul 29 22:31:29 CST 2020
pZxid = 0x5c
cversion = 2
dataVersion = 1
aclVersion = 3
ephemeralOwner = 0x0
dataLength = 9
numChildren = 2
  • Digest模式:
    命令:setAcl <path> digest:<user>:<password>:<acl>
    密码是经过SHA1以及BASE64处理的密文,在shell 中可以通过以下命令计算:
echo -n <user>:<password> | openssl dgst -binary -sha1 | openssl base64

建立新的窗口,计算密码

[root@izbp14najjyuhkvm4qbic7z bin]# echo -n qxy:123456 | openssl dgst -binary -sha1 | openssl base64
hDF4uLZvMJqOX2ekKFa6kSz9HNo=

实战:

[zk: localhost:2181(CONNECTED) 5] create /digestNode "digestNode"
Created /digestNode
[zk: localhost:2181(CONNECTED) 2] setAcl /digestNode digest:qxy:hDF4uLZvMJqOX2ekKFa6kSz9HNo=:cdrwa
[zk: localhost:2181(CONNECTED) 3] get /digestNode
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /digestNode
[zk: localhost:2181(CONNECTED) 2] setAcl /digestNode digest:qxy:hDF4uLZvMJqOX2ekKFa6kSz9HNo=:cdrwa
[zk: localhost:2181(CONNECTED) 3] get /digestNode
org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /digestNode
[zk: localhost:2181(CONNECTED) 4] getAcl /digestNode
Authentication is not valid : /digestNode
[zk: localhost:2181(CONNECTED) 5] addauth digest qxy:123456
[zk: localhost:2181(CONNECTED) 6] getAcl /digestNode
'digest,'qxy:hDF4uLZvMJqOX2ekKFa6kSz9HNo=
: cdrwa
[zk: localhost:2181(CONNECTED) 7] get /digestNode
digestNode
文章目录
  1. 1. 客户端、服务器命令
  2. 2. 节点属性
  3. 3. help命令
  4. 4. 新增、查询节点
  5. 5. 修改节点
  6. 6. 删除节点
  7. 7. 查看子节点列表
  8. 8. 查看节点状态
  9. 9. 监听器
  10. 10. 权限控制