zookeeper的特性与常用命令的使用
zookeeper是一个分布式的,开放源码的分布式应用程序协调服务,它是一个为分布式应用提供一致性服务的软件。
zookeeper的应用场景如下:
- 数据发布订阅
- 负载均衡
- 命名服务,例如分布式ID生成器
- Master选举
- 集群管理
- 配置管理,例如分布式配置中心
- 分布式队列
- 分布式锁
zookeeper的数据模型
zookeeper的数据存储是“树”状结构的,其中每个节点称为“数据节点”或ZNode,每个znode可以存储数据,还可以挂载子节点,因此可以称之为“树”,/为其根节点。znode节点可以细分为四种类型:
- PERSISTENT(持久节点):持久化在内存和磁盘(除非使用API强制删除)。
- PERSISTENT_SEQUENTIAL(持久顺序节点):在持久节点的基础上添加了顺序,zookeeper会自动在节点名后追加一个自增的整形数字。
- EPHEMERAL(临时节点):生命周期与客户端会话绑定,会话失效后节点会自动删除
- EPHEMERAL_SEQUENTIAL(临时顺序节点):在临时节点的基础上添加了顺序,zookeeper会自动在节点名后追加一个自增的10位整形数字(这个数字由父节点维护)。
持久节点和临时节点的区别:
- 持久节点会一直保存在内存和磁盘中,除非主动删除,临时节点会在会话关闭时自动删除。
- 持久节点下面可以创建子节点,而临时节点下面不能创建子节点。
zookeeper中的角色
- Leader(领导者):负责投票的发起和决议,更新系统状态。
- Learner(学习者):分为Follower和Observer。
- Follower(跟随者):用于接收客户端请求并返回结果,在选举过程中参与投票。
- Observer(观察者):可以接收客户端请求,将写请求转发给Leader,但不参与投票过程,目的是为了提高读取速度。
- Client(客户端):请求发起方。
常用命令
首先启动zookeeper服务器端,然后通过zkCli.sh
脚本启动客户端来链接zookeeper服务器端:
# sh /usr/local/zookeeper/bin/zkCli.sh
通过执行help命令,查询可用的zookeeper命令(随便输入一个zookeeper不存在的命令都会出现):
[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port -client-configuration properties-file cmd args
addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE
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 [-b batch size]
delquota [-n|-b] path
get [-s] [-w] path
getAcl [-s] path
getAllChildrenNumber path
getEphemerals path
history
listquota path
ls [-s] [-w] [-R] path
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]
set [-s] [-v version] path data
setAcl [-s] [-v version] [-R] path acl
setquota -n|-b val path
stat [-w] path
sync path
version
Command not found: Command not found help
ls
列出指定节点中下的所有子节点(不包含孙子节点)。
[zk: localhost:2181(CONNECTED) 1] ls /
[zookeeper]
create
创建一个新的节点。
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
- -e 创建临时节点
- -s 创建顺序节点
- acl 是针对这个节点创建一个权限的,如果创建权限了,则拥有权限的才可以访问
[zk: localhost:2181(CONNECTED) 3] create /a a
Created /a
[zk: localhost:2181(CONNECTED) 4] create -s /a/b
Created /a/b0000000000
[zk: localhost:2181(CONNECTED) 6] create /a/c
Created /a/c
[zk: localhost:2181(CONNECTED) 7] create -s /a/c/d
Created /a/c/d0000000000
每个路径下的顺序节点的编号都是从0开始自增,这个数字由父节点维护。
get
查看节点的内容。
[zk: localhost:2181(CONNECTED) 7] get /p
parent
set
修改节点的内容。
[zk: localhost:2181(CONNECTED) 9] set /p parent_node
[zk: localhost:2181(CONNECTED) 10] get /p
parent_node
stat
查询节点的状态。
[zk: localhost:2181(CONNECTED) 12] stat /p
cZxid = 0x200000006
ctime = Tue Aug 06 22:41:14 ICT 2019
mZxid = 0x200000007
mtime = Tue Aug 06 22:45:04 ICT 2019
pZxid = 0x200000006
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 11
numChildren = 0
- cZxid:节点被创建的zxid
- ctime:创建时间
- mZxid:节点最后一次修改的zxid
- mtime:修改时间
- pZxid:子节点(或该节点)的最近一次创建/删除的时间戳对应(不含孙子节点)
- cversion:子节点被修改的版本号
- dataVersion:节点被修改的版本号
- aclVersion:节点的ACL被修改的版本号
- ephemeralOwner:若此节点为临时节点,值为该节点拥有者的会话id,否则为0
- dataLength:数据长度
- numChildren:子节点个数(不含孙子节点)
Zxid是一个64位的数字,它高32位是epoch,用来标识leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,低32位是个递增计数。
delete
删除节点。
[zk: localhost:2181(CONNECTED) 14] delete /p
[zk: localhost:2181(CONNECTED) 15] ls /
[zookeeper]
deleteall
删除节点(支持递归删除)。
[zk: localhost:2181(CONNECTED) 26] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 27] create /a a
Created /a
[zk: localhost:2181(CONNECTED) 28] create /a/b b
Created /a/b
[zk: localhost:2181(CONNECTED) 29] delete /a
Node not empty: /a
[zk: localhost:2181(CONNECTED) 30] deleteall /a
[zk: localhost:2181(CONNECTED) 31] ls /
[zookeeper]
ACL机制
Zookeeper使用ACL来对节点znode做权限认证。
ACL语法格式:scheme:id:permissions
。
scheme表示采用哪一种认证机制,id的内容与前面的scheme有关,permissions表示相关权限(如只读,读写,管理等)。
zookeeper提供了如下几种机制(scheme):
world
:对应的id为anyone
,world:anyone
代表任何人都可以访问,也是默认的认证权限。auth
: 对应的id为username:password
,它需要先通过username:password
形式的authentication。digest
: 对应的id为username:BASE64(SHA1(password))
,它需要先通过username:password
形式的authentication。ip
: 对应的id为客户端的IP地址,设置的时候可以设置一个ip段,比如ip:192.168.1.0/16, 表示匹配前16个bit的IP段。
permissions:CREATE、DELETE、WRITE、READ、ADMIN也就是增、删、改、查、管理权限,这5种权限简写为cdrwa(即:每个单词的首字符缩写)
- CREATE©:创建子节点的权限。
- DELETE(d):删除节点的权限。
- READ®:读取节点数据的权限。
- WRITE(w):修改节点数据的权限。
- ADMIN(a):设置子节点权限的权限。
与ACL相关的命令:
- getAcl:获取指定节点的ACL信息。
- setAcl:设置指定节点的ACL信息。
- addauth:注册会话授权信息。
world
scheme的使用:
[zk: localhost:2181(CONNECTED) 17] create /a
Created /a
[zk: localhost:2181(CONNECTED) 19] getAcl /a
'world,'anyone
: cdrwa
auth
scheme的使用:
[zk: localhost:2181(CONNECTED) 0] addauth digest morris:123456 # 需要先添加一个用户然后进行登录
[zk: localhost:2181(CONNECTED) 1] setAcl /b auth:morris:123456:cwra # 然后才可以拿着这个用户去设置权限
[zk: localhost:2181(CONNECTED) 2] getAcl /b # 密码是以密文的形式存储的
'digest,'morris:RFNk4yqivnCw1D/l0vH0i2rPRBI=
: crwa
[zk: localhost:2181(CONNECTED) 21] create /b/c
Created /b/c
[zk: localhost:2181(CONNECTED) 25] getAcl /b/c
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 11] delete /b/c # 由于没有d权限,所以提示无法删除
Authentication is not valid : /b/c
退出客户端后,重新进入:
[zk: localhost:2181(CONNECTED) 4] getAcl /b # 没有权限无法访问
Authentication is not valid : /b
[zk: localhost:2181(CONNECTED) 8] addauth digest morris:123456
[zk: localhost:2181(CONNECTED) 9] getAcl /b # 重新登录后可以访问了
'digest,'morris:RFNk4yqivnCw1D/l0vH0i2rPRBI=
: crwa
digest
scheme的使用:
[zk: localhost:2181(CONNECTED) 10] create /c
Created /c
[zk: localhost:2181(CONNECTED) 11] setAcl /c digest:morris:RFNk4yqivnCw1D/l0vH0i2rPRBI=:crwa
[zk: localhost:2181(CONNECTED) 12] getAcl /c
'digest,'morris:RFNk4yqivnCw1D/l0vH0i2rPRBI=
: crwa
[zk: localhost:2181(CONNECTED) 13] create /c/e
Created /c/e
[zk: localhost:2181(CONNECTED) 14] getAcl /c/e
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 15] delete /c/e
Authentication is not valid : /c/e
那么怎么通过密码获得密文呢?
# java -Djava.ext.dirs=/usr/local/zookeeper/lib -cp /usr/local/zookeeper/lib/zookeeper-3.6.2.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider morris:123456
morris:123456->morris:RFNk4yqivnCw1D/l0vH0i2rPRBI=
ip
scheme的使用:
[zk: localhost:2181(CONNECTED) 38] create /f
Created /f
[zk: localhost:2181(CONNECTED) 39] setAcl /f ip:10.1.9.98:crwa
使用ip为10.1.9.98
连接zookeeper:
[zk: 10.0.4.105:2181(CONNECTED) 1] getAcl /f
'ip,'10.1.9.98
: crwa
ZooKeeper 常用四字命令
ZooKeeper支持某些特定的四字命令与其进行交互,用来获取ZooKeeper服务的当前状态及相关信息,可通过telnet或nc向ZooKeeper提交相应的命令:
- stat:查看哪个节点被选择作为follower或者leader。
- ruok:测试是否启动了该Server,若回复imok表示已经启动。
- dump:列出未经处理的会话和临时节点。
- kill:关掉server。
- conf:输出相关服务配置的详细信息。
- cons:列出所有连接到服务器的客户端的完全的连接/会话的详细信息。
- envi:输出关于服务环境的详细信息(区别于conf命令)。
- reqs:列出未经处理的请求。
- wchs:列出服务器watch的详细信息。
- wchc:通过session列出服务器watch的详细信息,它的输出是一个与watch相关的会话的列表。
- wchp:通过路径列出服务器watch的详细信息。它输出一个与session相关的路径。
telnet提交四字命令的例子:
# telnet localhost 2181
Trying ::1...
Connected to localhost.
Escape character is '^]'.
stat
Zookeeper version: 3.6.2--803c7f1a12f85978cb049af5e4ef23bd8b688715, built on 09/04/2020 12:44 GMT
Clients:
/0:0:0:0:0:0:0:1:43080[0](queued=0,recved=1,sent=0)
/10.1.9.98:6401[1](queued=0,recved=2,sent=2)
Latency min/avg/max: 3/3.0/3
Received: 4
Sent: 3
Connections: 2
Outstanding: 0
Zxid: 0x10000003e
Mode: follower
Node count: 14
Connection closed by foreign host.
nc提交四字命令的例子:
# echo srvr|nc 127.0.0.1 2181
Zookeeper version: 3.6.2--803c7f1a12f85978cb049af5e4ef23bd8b688715, built on 09/04/2020 12:44 GMT
Latency min/avg/max: 0/0.6923/3
Received: 17
Sent: 16
Connections: 2
Outstanding: 0
Zxid: 0x10000003e
Mode: follower
Node count: 14
如果没有安装nc,请先安装yum install -y nc
。