1. ZooKeeper的特性
ZooKeeper的特性主要从会话、数据节点,版本,Watcher,ACL权限控制,集群角色这些部分来了解,其中需要重点掌握的数据节点与Watcher
1.1 会话
客户端与服务端的一次会话连接,本质是TCP长连接,通过会话可以进行心跳检测和数据传输
会话(session)是zookepper非常重要的概念,客户端和服务端之间的任何交互操作都与会话有关
会话状态
根据上图,ZooKeeper客户端和服务端成功连接后,就创建了一次会话,ZooKeeper会话在整个运行期间的生命周期中,会在不同的会话状态之间切换,这些状态包括:
CONNECTING、CONNECTED、RECONNECTING、RECONNECTED、CLOSE
一旦客户端开始创建ZooKeeper对象,那么客户端状态就会变成CONNECTING状态,同时客户端开始尝试连接服务端,连接成功后,客户端状态变为CONNECTED,通常情况下,由于断网或其他原因,客户端与服务端之间会出现断开情况,一旦碰到这种情况,ZooKeeper客户端会自动进行重连服务,同时客户端状态再次变成CONNECTING,直到重新连上服务端后,状态又变为CONNECTED,在通常情况下,客户端的状态总是介于CONNECTING和CONNECTED之间。但是,如果出现诸如会话超时、权限检查或是客户端主动退出程序等情况,客户端的状态就会直接变更为CLOSE状态
1.2 数据模型
ZooKeeper的视图结构和标准的Unix文件系统类似,其中每个节点称为“数据节点”或ZNode,每个ZNode可以存储数据,还可以挂载子节点,因此可以称之为“树”;第二点需要注意的是,每一个znode都必须有值,如果没有值,节点是不能创建成功的
- 在ZooKeeper中,ZNode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据
- 通过客户端可对ZNode进行增删改查的操作,还可以注册watcher监控ZNode的变化
1.3 ZooKeeper节点类型
1. Znode有两种类型
- 短暂(ephemeral)(create -e /app1/test1 “test1” 客户端断开连接zk删除ephemeral类型节点)
- 持久(persistent) (create -s /app1/test2 “test2” 客户端断开连接zk不删除persistent类型节点)
临时节点不能创建子节点
2. Znode有四种形式的目录节点(默认是persistent )
- PERSISTENT
- PERSISTENT_SEQUENTIAL(持久序列/test0000000019 )
- EPHEMERAL
- EPHEMERAL_SEQUENTIAL
3. 创建znode时设置顺序标识,znode名称后会附加一个值,顺序号是一个单调递增的计数器,由父节点维护
4. 在分布式系统中,顺序号可以被用于为所有的事件进行全局排序,这样客户端可以通过顺序号推断事件的顺序
1.4 ZooKeeper节点状态属性
属性 | 数据结构 | 描述 |
zxid | long | 致使ZooKeeper节点状态改变的每一个操作都将使节点接收到一个zxid格式的时间戳 |
czxid | long | 节点被创建的时间对应zxid格式的时间戳 |
mzxid | long | 节点被修改的时间对应zxid格式的时间戳【与子节点无关】 |
pzxid | long | 子节点最近一次创建/修改的时间对应zxid格式的时间戳【和孙子节点无关】 |
ctime | long | 节点被创建的时间 |
mtime | long | 节点最后一次被修改的时间 |
version | long | 节点被修改产生的版本号 |
cversion | long | 子节点被修改产生的版本号 |
aversion | long | 节点的ACL被修改的版本号 |
emphemeralOwner | long | 如果此节点为临时节点,那么它的值为这个节点拥有者的会话ID;否则,它的值为0 |
dataLength | int | 节点数据域的长度 |
numChildren | int | 节点拥有子节点的个数 |
1.5 ACL权限控制机制
ACL机制,表示为scheme:id:permissions,第一个字段表示授权策略,第二个id表示授权对象,permissions表示授予的权限(如只读,读写,管理等)
1.5.1 scheme:授权策略
- world:只有一个id叫做anyone,world:anyone对应任何人,在zookeeper中表示所有人都有权限的节点
- auth:id一般是username:password,代表已经认证通过的用户(可以通过addauth digest user:pwd 来添加授权用户)
- digest:它对应的id为username:BASE64(SHA1(password)),它需要先通过username:password形式的authentication
- ip:使用IP地址认证,id一般是客户机的ip地址
1.5.2 id:授权对象
- world策略的id只能是anyone
- auth策略的id一般是username:password
- digest策略的id是username:BASE64(SHA1(password))
- ip策略的id就是客户端的IP地址
1.5.3 permissions:授予的权限
CREATE【增】、READ【读】、WRITE【写、修改】、DELETE【删】、ADMIN【管理、授权】,简写即crwda
- CREATE【c】:创建子节点的权限
- READ【r】:读取节点数据的权限
- WRITE【w】:修改节点数据的权限
- DELETE【d】:删除子节点的权限
- ADMIN【a】:给子节点授权的权限
1.6 Watcher监听机制
Watcher 监听机制是 Zookeeper 中非常重要的特性,我们基于 zookeeper 上创建的节点,可以对这些节点绑定监听事件,比如可以监听节点数据变更、节点删除、子节点状态变更等事件,通过这个事件机制,可以基于 zookeeper实现分布式锁、集群管理等功能
watcher 特性
- 当数据发生变化的时候, zookeeper 会产生一个 watcher 事件,并且会发送到客户端。但是客户端只会收到一次通知
- 如果后续这个节点再次发生变化,那么之前设置 watcher 的客户端不会再次收到消息。watcher 是一次性的操作,可以通过循环监听去达到永久监听效果
如何注册事件机制
- ZooKeeper 的 Watcher 机制,总的来说可以分为三个过程:客户端注册 Watcher、服务器处理 Watcher 和客户端回调 Watcher客户端
- 注册 watcher 有 3 种方式,getData、exists、getChildren
2. ZooKeeper的常用命令
2.1 服务端
通过bin目录下的zkServer.sh脚本进行服务端的相关操作
- 启动服务:./zkServer.sh start
- 服务状态查看:./zkServer.sh status
- 停止服务
- 重启服务
2.2 客户端
连接zookeeper服务:./zkCli.sh -server ip:port,连接成功后,系统会输出ZooKeeper 的相关环境以及配置信息
节点其实就是一个目录、文件
2.2.1 create [-e] [-s] path data [acl]
创建节点
1. 不加参数是创建持久节点
2. 使用-e参数创建一个临时节点
3. 使用-s参数创建一个有序号的节点
4. 使用acl参数创建节点时,给节点授予指定权限【crwda】
2.2.2 ls path
使用ls命令查看ZooKeeper的path路径下包含的节点。ls /是查看zookeeper根目录下的所有节点
2.2.3 ls2 path
查看path路径下的所有节点,并且显示出当前节点path的一些状态信息
2.2.4 get path [watch]
查看节点内容
可以使用watch设置监听,下一次写操作【修改、删除、设置子节点】时触发监听,但是只能生效一次
2.2.5 set path
修改path节点内容
2.2.6 delete path
删除path节点
2.2.7 rmr path
递归删除
path节点如果有子节点使用delete命令就不能删除了,这时就可以使用rmr命令了
2.2.8 其他一些常用命令
quit 退出客户端
help 帮助命令
2.3 ACL权限控制
ZooKeeper的ACL(Access Control List),分为三个维度:scheme、id、permission。通常表示为:scheme:id:permission
- schema:代表授权策略。world、auth、digest、ip
- id:代表用户
- world对应id:anyone
- auth对应id:username:password
- digest对应id:username:BASE64(SHA1(password))
- ip对应id:客户端ip地址
- permission:代表权限。CREATE、READ、WRITE、DELETE、ADMIN,简写crwda
2.3.1 getAcl命令
获取指定节点的ACL信息
2.3.2 setAcl命令
设置指定节点的ACL信息
2.3.3 addauth命令
addauth digest username:pwd;
注册会话授权信息
常用授权方式有两种,auth和digest
2.3.3.1 auth
授权前必须使用addauth添加一个用户,否则会报错
由于/test/children01节点没有d的权限,所以无法删除/test/children01/testa节点
断开客户端重新连接测试:
需要重新新增权限才可以访问
2.3.3.2 digest
auth与digest的区别就是,前者使用明文密码进行登录,后者使用密文密码进行登录
注意:这里如果使用明文,会导致该znode不可访问
这里密文的获取可以使用如下方式:
java -Djava.ext.dirs=/soft/zookeeper/lib -cp /soft/zookeeper/zookeeper-3.4.12.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider user1:123456
断开客户端重新连接:
需要添加用户认证才可以使用
2.3.4 acl命令ip
2.3.5 acl设置r权限,无法删除
setAcl权限的时候由于失误,导致节点无法删除
create /test/node1 enjoy
setAcl /test world:anyone:r
这个时候无论是delete 还是rmr都没有权限删除
解决方式:启用super权限
使用DigestAuthenticationProvider.generateDigest("super:admin"); 获得密码
1. 修改zkServer启动脚本增加
"-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs="
2. 启动客户端用管理员登陆
addauth digest super:admin
2.4 常用四字命令
ZooKeeper 支持某些特定的四字命令字母与其的交互。用来获取 ZooKeeper 服务的当前状态及相关信息。可通过 telnet 或 nc 向 ZooKeeper 提交相应的命令
echo stat|nc 127.0.0.1 2181 | 查看哪个节点被选择作为follower或者leader |
echo ruok|nc 127.0.0.1 2181 | 测试是否启动了该Server,若回复imok表示已经启动 |
echo conf | nc 127.0.0.1 2181 | 输出相关服务配置的详细信息 |
echo reqs | nc 127.0.0.1 2181 | 列出未经处理的请求 |
echo wchs | nc 127.0.0.1 2181 | 列出服务器 watch 的详细信息 |
echo kill | nc 127.0.0.1 2181 | 关掉server |