zookeeper的基本概念
zookeeper是一款开源的分布式协调服务框架,为分布式环境提供了一致性服务的功能,常见应用场景有:发布订阅,主动通知,文件管理,集群管理,分布式锁等功能。zk在设计的时候满足了cp两要素,即一致性和分区容错性。
zookeeper的设计理念
这里我参考以往的一些经验,将其简单囊括为了以下几点:
一致性
如下图所示,所有的客户端一旦连接到了集群环境中,不论访问的zk是leader角色还是follower角色,每个zk节点的数据都是相同的。假设某一时刻,zk的某个节点数据被修改了,那么此时必须要将每个节点的数据都做同步之后才能继续提供外界读取节点的功能。
有头
在集群环境中,一定会有一个leader的角色充当集群领头。一旦leader挂了,就会重新选举新的机器当选leader。
数据树
zk内部存储数据是采用了树状结构,这一点有些类似于文件系统的设计,每个树状节点底下存放的子节点可以是有序排列的状态 , 如下图所示:
zookeeper内部的相关配置信息
常规配置文件内容
使用的zk版本为3.4.14版本
# zookeeper时间配置中的基本单位 (毫秒) tickTime=2000 # 允许follower初始化连接到leader最大时长,它表示tickTime时间倍数 即:initLimit*tickTime initLimit=10 # 允许follower与leader数据同步最大时长,它表示tickTime时间倍数 syncLimit=5 # 存放节点数据的位置 dataDir=/Users/linhao/env/zookeeper/zk-data # 端口号 clientPort=2181 # 最大并发连接数 #maxClientCnxns=60 # # Be sure to read the maintenance section of the # administrator guide before turning on autopurge. # # http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance # # The number of snapshots to retain in dataDir #autopurge.snapRetainCount=3 # Purge task interval in hours # Set to "0" to disable auto purge feature #autopurge.purgeInterval=1 #日志地址 dataLogDir=/Users/linhao/env/zookeeper/zk-log # 保存的数据快照数量,之外的将会被清除 autopurge.snapRetainCount=3 #自动触发清除任务时间间隔,小时为单位。默认为0,表示不自动清除。 autopurge.purgeInterval=1 复制代码
内部指令整理
启动zookeeper脚本
sh ./zkServer.sh start 复制代码
连接服务端指令
sh ./zkCli.sh 复制代码
节点的增删改查
ls / 查询所有根节点 ls /idea 查询idea节点下边的内容 delete /idea 删除idea节点 delete /idea/node-1 删除idea节点下边的node-1子节点 create /idea/node-2 "v1" 创建idea/node-2节点 并且写入v1值 get /idea/node-1 获取相关节点 复制代码
节点类型
持久化节点
默认创建的节点就是持久化类型
create /node "" 复制代码
临时节点
在zookeeper3.4版本里面,创建临时节点的时候可能会有以下异常:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at org.apache.zookeeper.ZooKeeperMain.processZKCmd(ZooKeeperMain.java:707) 复制代码
临时节点正确的执行命令为:
create -e /temp "" 复制代码
持久化顺序节点
create -s /seq-node "" 复制代码
多次执行该指令之后可以看到以下内容:
[zk: localhost:2181(CONNECTED) 4] ls / [dubbo, seq-node0000000010, ietty, zookeeper, idea] [zk: localhost:2181(CONNECTED) 5] create -s /seq-node "" Created /seq-node0000000011 [zk: localhost:2181(CONNECTED) 6] create -s /seq-node "" Created /seq-node0000000012 [zk: localhost:2181(CONNECTED) 7] create -s /seq-node "" Created /seq-node0000000013 [zk: localhost:2181(CONNECTED) 8] create -s /seq-node "" Created /seq-node0000000014 复制代码
此时节点的下方已经创建了多个顺序节点数据
临时顺序节点
create -e -s /seq-temp-node "" 复制代码
查看节点信息
stat命令可以查看节点底下的各种属性 [zk: localhost:2181(CONNECTED) 12] stat /idea //创建节点的事务id cZxid = 0x1bd6 //创建节点的时间 ctime = Sun Nov 08 22:50:57 CST 2020 //修改节点的事务id mZxid = 0x1bd6 //最后修改时间 mtime = Sun Nov 08 22:50:57 CST 2020 //子节点变更的事务ID pZxid = 0x1bdb //子节点的变更次数 cversion = 4 dataVersion = 0 //权限版本 aclVersion = 0 ephemeralOwner = 0x0 //数据长度 dataLength = 12 //第一层子节点的数目 不包含子子节点 numChildren = 2 复制代码
acl权限设置
ACL全称为Access Control List(访问控制列表),用于控制资源的访问权限。ZooKeeper使用ACL来控制对其znode的防问。基于scheme🆔permission的方式进行权限控制。scheme表示授权模式、id模式对应值、permission即具体的增删改权限位。
scheme认证模型
方案 | 描述 |
world | 开放模式,world表示全世界都可以访问(这是默认设置) |
ip | ip模式,限定客户端IP防问 |
auth | 用户密码认证模式,只有在会话中添加了认证才可以防问 |
digest | 与auth类似,区别在于auth用明文密码,而digest 用sha-1+base64加密后的密码。在实际使用中digest 更常见。 |
permission权限位
权限位 | 权限 | 描述 |
c | CREATE | 可以创建子节点 |
d | DELETE | 可以删除子节点(仅下一级节点) |
r | READ | 可以读取节点数据及显示子节点列表 |
w | WRITE | 可以设置节点数据 |
a | ADMIN | 可以设置节点访问控制列表权限 |
acl 相关命令
命令 | 描述 |
getAcl | getAcl |
setAcl | setAcl |
addauth | addauth |
world权限示例 语法: setAcl world:anyone:<权限位> 注:world模式中anyone是唯一的值,表示所有人
查看默认节点权限:
#创建一个节点 create -e /testAcl #查看节点权限 getAcl /testAcl #返回的默认权限表示 ,所有人拥有所有权限。 'world,'anyone: cdrwa 修改默认权限为 读写 #设置为rw权限 setAcl /testAcl world:anyone:rw # 可以正常读 get /testAcl # 无法正常创建子节点 create -e /testAcl/t "hi" # 返回没有权限的异常 Authentication is not valid : /testAcl/t 复制代码
zookeeper集群
建议最少要有三台服务器。
这两种场景下会有选举发生:
1.服务节点初始化
2.或者半数以上的节点无法和leader进行连接建立
集群里面的zk机器均具有读和写的功能。
zk集群的选举
在讲解选举之前,我们需要先了解一下什么是zxid。
在zk的节点数据中,每次发生数据变动都会有一个流水id做递增的记录,这个id我们称之为zxid,不同机器的zxid可能会有所不同,越大代表当前的数据越新。实际上每个zk节点都有两个用于记录更新的id,分别是czxid和mzxid。通过名称的缩写可以翻译为:
czxid:创建节点时候的xid。
mzxid:修改节点数据时候的xid。