介绍
Zookeeper是分布式应用协调框架,用于解决一些数据管理问题,如配置管理,集群管理,状态同步管理等。可理解为是一种基于内存的数据库,采用文件系统(树形)数据结构以及事件监听机制。
节点(znode)
znode对应的就是文件系统数据结构中的一个"目录"。
znode的四种类型:
- 持久节点
[zk: localhost:2181(CONNECTED) 0] create /heoller Created /heoller [zk: localhost:2181(CONNECTED) 1] get -s /heoller null # 数据 cZxid = 0x4 # 创建时的事务id ctime = Sun Nov 22 16:40:54 CST 2020 # 创建时间 mZxid = 0x4 # 修改的事务id mtime = Sun Nov 22 16:40:54 CST 2020 # 修改时间 pZxid = 0x4 # 子节点新增或删除时的事务id cversion = 0 # 创建时的版本 dataVersion = 0 # 数据版本 aclVersion = 0 # acl的版本 ephemeralOwner = 0x0 # 临时节点的owner,0表示持久节点,非0表示当前客户端连接的sessionId dataLength = 0 # 数据长度 numChildren = 0 # 子节点数
- 持久+序列化节点
[zk: localhost:2181(CONNECTED) 2] create -s /heoller/aaa- Created /heoller/aaa-0000000000 [zk: localhost:2181(CONNECTED) 3] create -s /heoller/aaa- Created /heoller/aaa-0000000001
- 临时节点
[zk: localhost:2181(CONNECTED) 4] create -e /temp Created /temp [zk: localhost:2181(CONNECTED) 5] get -s /temp null cZxid = 0x7 ctime = Sun Nov 22 16:46:55 CST 2020 mZxid = 0x7 mtime = Sun Nov 22 16:46:55 CST 2020 pZxid = 0x7 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x1000448f3c20001 dataLength = 0 numChildren = 0
- 临时+序列化节点
[zk: localhost:2181(CONNECTED) 1] create /temp-seq Created /temp-seq [zk: localhost:2181(CONNECTED) 2] create -e -s /temp-seq/seq- Created /temp-seq/seq-0000000000 [zk: localhost:2181(CONNECTED) 3] create -e -s /temp-seq/seq- Created /temp-seq/seq-0000000001 [zk: localhost:2181(CONNECTED) 4] ls -R /temp-seq /temp-seq /temp-seq/seq-0000000000 /temp-seq/seq-0000000001
事件监听机制
- 监听节点数据
节点被删除或者内容发生变化,对应客户端会被通知。[zk: localhost:2181(CONNECTED) 0] create /test Created /test [zk: localhost:2181(CONNECTED) 1] get -w /test null [zk: localhost:2181(CONNECTED) 2] set /test heoller WATCHER:: WatchedEvent state:SyncConnected type:NodeDataChanged path:/test
- 监听"目录"
"目录"下的子节点发生新增或删除时,对应客户端会被通知。[zk: localhost:2181(CONNECTED) 3] ls -w /test [] [zk: localhost:2181(CONNECTED) 4] create /test/aaa WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/test Created /test/aaa [zk: localhost:2181(CONNECTED) 5] ls -w /test [aaa] [zk: localhost:2181(CONNECTED) 6] delete /test/aaa WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/test
- 监听递归子节点
1和2的结合。[zk: localhost:2181(CONNECTED) 18] ls -R -w /test /test /test/sub0 /test/sub1 /test/sub2 /test/sub0/sub0 [zk: localhost:2181(CONNECTED) 19] set /test aaa WATCHER:: WatchedEvent state:SyncConnected type:NodeDataChanged path:/test [zk: localhost:2181(CONNECTED) 29] ls -R -w /test /test /test/sub0 [zk: localhost:2181(CONNECTED) 30] create /test/sub1 WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/test Created /test/sub1 [zk: localhost:2181(CONNECTED) 31] create /test/sub0/sub0 WATCHER:: WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/test/sub0 Created /test/sub0/sub0
所有监听都是一次性的,触发之后,监听就会被移除
ACL权限控制
ACL说明
由权限模式+授权对象+权限信息组成。可以通过系统参数zookeeper.skipACL控制是否跳过权限检测,默认为不跳过。
- 权限模式(Scheme)
即权限验证方式,支持范围模式,口令模式(用户名密码)以及Super权限模式。- 范围模式(IP模式)
可以对指定ip或ip段的客户端赋予权限。 - 口令模式(Digest模式)
服务端通过账密验证客户端权限。 - Super权限模式
具有该权限的客户端有操作数据节点的任意权限
- 范围模式(IP模式)
- 授权对象(ID)
对于范围模式,授权对象是IP或IP段;对于Digest/Super模式,授权对象是具体用户;对于World模式,授权对象是所有用户。
生成授权ID方法:- 代码方式
DigestAuthenticationProvider.generateDigest("user:password");
- shell方式
echo ‐n <user>:<password> | openssl dgst -binary -sha1 | openssl base64
- 代码方式
- 权限信息(Permission)
指具体的操作权限。- c 创建,可以在授权节点下创建子节点。
- w 更新(写)
- r 读取
- d 删除,可以删除授权节点下的子节点。
- a 管理者(admin)
ACL示例
密文方式
➜ ~ echo -n heoller:123456 | openssl dgst -binary -sha1 | openssl base64 tcQjGGQnqBWfeXxNnaIrU4A7pTw=
[zk: localhost:2181(CONNECTED) 1] create /nodeWithACL aclnode digest:heoller:tcQjGGQnqBWfeXxNnaIrU4A7pTw=:rw # 此时只有heoller用户才有权限访问了 [zk: localhost:2181(CONNECTED) 2] get /nodeWithACL org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /nodeWithACL # 需要添加授权信息才有权限 [zk: localhost:2181(CONNECTED) 3] addauth digest heoller:123456 [zk: localhost:2181(CONNECTED) 14] get /nodeWithACL aclnode
明文方式
# 先登录,再使用auth授权 [zk: localhost:2181(CONNECTED) 0] addauth digest iholen:111111 [zk: localhost:2181(CONNECTED) 1] create /nodeDigest mingwen auth:iholen:111111:rw Created /nodeDigest
[zk: localhost:2181(CONNECTED) 1] get /nodeDigest org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /nodeDigest [zk: localhost:2181(CONNECTED) 2] addauth digest iholen:111111 [zk: localhost:2181(CONNECTED) 3] get /nodeDigest mingwen
IP模式
create /ipnode ipnode ip:192.168.1.161:rw setAcl /ipnode ip:192.168.1.161:rw,ip:192.168.1.162:rw
Super模式
-Dzookeeper.DigestAuthenticationProvider.superDigest=super:admin:x1nq8J5GOJVPY6zgzhtTtA9izLc=
事务日志
客户端每次事务操作,服务端都会将这些操作记录在事务日志中,事务日志默认存放在dataDir中,可通过设置dataLogDir设置存储路径。zk在存储事务日志时会频繁的进行磁盘IO,为了提升效率,zk创建事务日志文件时就进行了文件空间的预分配,预分配的空间大小可以通过zookeeper.preAllocSize
参数设置。
zk提供了查看事务日志的工具,org.apache.zookeeper.server.LogFormatter
➜ ~ cd /Users/henry/zookeeper/lib ➜ lib> java -classpath .:slf4j-api-1.7.25.jar:zookeeper-3.6.1.jar:zookeeper-jute-3.6.1.jar org.apache.zookeeper.server.LogFormatter /Users/henry/zookeeper/data/version-2/log.1 SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. ZooKeeper Transactional Log File with dbid 0 txnlog format version 2 20-11-28 上午12时03分31秒 session 0x10004e9a70f0000 cxid 0x0 zxid 0x1 createSession 30000 2,1371985504 20-11-28 上午12时03分45秒 session 0x10004e9a70f0000 cxid 0x2 zxid 0x2 closeSession v{} 2,1371985504 20-11-28 上午12时03分49秒 session 0x10004e9a70f0001 cxid 0x0 zxid 0x3 createSession 30000 2,1371985504 20-11-28 上午12时03分55秒 session 0x10004e9a70f0001 cxid 0x1 zxid 0x4 create '/node1,#6e6f646531,v{s{31,s{'world,'anyone}}},F,1 2,7175659339 20-11-28 上午12时03分57秒 session 0x10004e9a70f0001 cxid 0x2 zxid 0x5 closeSession v{} 2,7175659339 EOF reached after 5 txns.
数据快照
用于记录服务器某一时刻的全量数据,可通过snapCount
设置每多少次事务操作生成一次快照.
java -classpath .:slf4j-api-1.7.25.jar:zookeeper-3.6.1.jar:zookeeper-jute-3.6.1.jar org.apache.zookeeper.server.SnapshotFormatter /Users/henry/zookeeper/data/version-2/snapshot.0
事务日志和数据快照为什么都要有?
快照用于快速恢复数据,反应了当时数据的状态,事务日志是全面的日志,在恢复数据时,可以先恢复快照数据,然后再通过事务日志进行增量恢复。