zk 基本数据模型介绍
- 是一个树形结构,类似于前端开发中的tree.js组件
- zk的数据模型可以理解为ilnux/unix的文件目录:/usr/local...
- 每一个节点都称为znode,它可以有子节点,也可以有数据
- 每个节点分为临时节点和永久节点,临时节点在客户端断开后消失
- 每个节点都有各自的版本号,可以通过命令行来显示节点信息
- 每当节点数据发生变化,那么该节点的版本号会累加(乐观锁)
- 删除/修改过时的节点,版本号不匹配则会报错(类似乐观锁机制)
- 每个zk节点存储的数据不宜过大,几k即可
- 节点可以设置权限acl,可以通过权限来限制用户访问
zk的作用提现
- master节点选举,主节点挂了以后,从节点就会接手工作,并且保证这个节点是唯一的,这也是所谓首脑模式 ,从而保证我们的集群是高可用的
- 统一配置文件管理,即只需要部署一台服务器,则可以把相同的配置文件同步更新到其他所有服务器,此操作在云计算中用的特别多(假设修改了redis统一配置)
- 发布与订阅,类似消息队列MQ(amq,rmq....),dubbo发布者把数据存在znode上,订阅者会读取这个数据
- 提供分布式锁,分布式环境中不同进程之间争夺资源,类似于多线程中的锁
- 集群管理,集群中保证数据的强一致性
zk常用命令行操作
- 通过 ./zkCli.sh打开zk的客户端进行命令行后台
- ls 命令 与 ls2命令
- stat 命令 和 get命令
查看状态信息 和获取新增数据信息
[zk: localhost:2181(CONNECTED) 2] stat /
cZxid = 0x0 创建之后分配的id
ctime = Thu Jan 01 08:00:00 CST 1970 节点创建的时间
mZxid = 0x0 修改后zk分配的id
mtime = Thu Jan 01 08:00:00 CST 1970 修改节点时间
pZxid = 0x0 子节点id
cversion = -1 子节点version
dataVersion = 0 当前数据版本号
aclVersion = 0 权限版本号
ephemeralOwner = 0x0
dataLength = 0 数据长度
numChildren = 1 子节点数量
zk特性-
- session的基本原理一
- 客户端与服务端之间的连接存在会话
- 每个会话都会设置一个超时时间
- 心跳结束,session则过期
- session的基本原理二
- Session过期,则临时节点znode会被抛弃
- 心跳机制:客户端向服务端的ping包请求
节点操作
- 创建一个节点
[zk: localhost:2181(CONNECTED) 5] create /imooc imooc-data
Created /imooc
[zk: localhost:2181(CONNECTED) 6] get /imooc
imooc-data
[zk: localhost:2181(CONNECTED) 7] stat /imooc
cZxid = 0x4
ctime = Wed Apr 22 11:32:34 CST 2020
mZxid = 0x4
mtime = Wed Apr 22 11:32:34 CST 2020
pZxid = 0x4
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 10
numChildren = 0
- 创建一个临时节点 create -e
[zk: localhost:2181(CONNECTED) 19] create -e /imooc/tmp imooc-data
Created /imooc/tmp
zk断掉之后,临时节点不会立即删除,有一个心跳机制检测才会删除
[zk: localhost:2181(CONNECTED) 0] ls /imooc
[tmp]
[zk: localhost:2181(CONNECTED) 1] ls /imooc
[]
- 创建一个顺序节点 crete -s
[zk: localhost:2181(CONNECTED) 0] create -s /imooc/sec seq
Created /imooc/sec0000000002
- set命令设置值
[zk: localhost:2181(CONNECTED) 7] set /imooc new-data
[zk: localhost:2181(CONNECTED) 9] get /imooc
new-data
- delete 命令
根据版本号删除
delete -v [version] path
[zk: localhost:2181(CONNECTED) 38] delete -v 1 /imooc0000000003
version No is not valid : /imooc0000000003
zk特性-watcher机制
- ======一======
- 针对每个节点的操作,都会有一个监督者->wathcer
- 当监控的某个对象(znode)发生了变化,则触发wathcer事件
- zk中的wathcer是一次性的,触发后立即销毁
- ==二==
- 父节点,子节点,增删改都能够触发其wathcer
- 针对不同类型的操作,触发的wacher事件也不同:
- (子)节点创建事件
- (子)节点删除事件
- (子)节点数据变化事件
Watcher命令行学习
- 通过stat/get path [watch]设置watcher
- 父节点增删改操作触发watcher
- 子节点增删改操作触发watcher
Watcher事件类型一
- 创建父节点触发:NodeCreated
[zk: localhost:2181(CONNECTED) 46] stat -w /node
Node does not exist: /node
[zk: localhost:2181(CONNECTED) 47] create /node 456
WATCHER::
WatchedEvent state:SyncConnected type:NodeCreated path:/node
Created /node
- 修改父节点数据触发:NodeDataChanged
使用get设置一个事件
[zk: localhost:2181(CONNECTED) 55] get -w /new-node
234
[zk: localhost:2181(CONNECTED) 56] set /new-node 999
WATCHER::
WatchedEvent state:SyncConnected type:NodeDataChanged path:/new-node
- 删除父节点触发:NodeDeleted
[zk: localhost:2181(CONNECTED) 58] get -w /new-node
999
[zk: localhost:2181(CONNECTED) 59] delete /new-node
WATCHER::
WatchedEvent state:SyncConnected type:NodeDeleted path:/new-node
Watcher事件类二
新增和删除相对于父节点来说,子节点新增和删除是不管的,都是发生了变化
- ls为父节点设置watcher,创建子节点触发:NodeChildrenChanged
[zk: localhost:2181(CONNECTED) 60] ls -w /imooc
[sec0000000003, sec0000000004, sec0000000005]
[zk: localhost:2181(CONNECTED) 61] create /imooc/abc 123
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/imooc
Created /imooc/abc
- ls为父节点设置watcher,删除子节点触发:NodeChildrenChanged
[zk: localhost:2181(CONNECTED) 67] ls -w /imooc
[abc, sec0000000004, sec0000000005]
[zk: localhost:2181(CONNECTED) 68] delete /imooc/abc
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/imooc
- ls为父节点设置watcher,修改子节点不触发事件
[zk: localhost:2181(CONNECTED) 71] ls -w /imooc
[sec0000000004, sec0000000005]
[zk: localhost:2181(CONNECTED) 72] set /imooc/sec0000000004 123
watcher使用场景
- 统一资源配置
主机一 : 主机更新节点为新的配置信息->更新客户端配置1
主机二: 更新客户端配置2
主机三: 更新客户端配置3
ACL(access control lists)权限控制
- 针对节点可以设置相关读写等权限,目的为了保障数据安全性
- 权限permissions可以指定不同的权限范围及角色
ACL命令行
- getAcl : 获取某个节点的acl权限信息
- setAcl : 设置某个节点的acl权限信息
- addauth : 输入认证授权信息,注册时输入明文密码(登录)但是在zk的系统里,密码是加密形式存在的
[zk: localhost:2181(CONNECTED) 9] getAcl /imooc/abc
'world,'anyone
: cdrwa
ACL的构成 一
- zk的acl通过[scheme:id:permissions]来构成权限列表
- scheme:代表采用的某种权限机制
- id:代表允许访问的用户
- permissions:权限组合字符串
ACL的构成二- scheme
- world : world下只有一个id,即只有一个用户,也就是anyone,那么组合的写法就是world:anyone:[permissions]
- auth:代表认证登录,需要注册用户有权限就可以,形式为auth:user:password:[permissions]
- digest:需要对密码加密才能访问,组合形式为digest:username:BASE64(SHA1(password)):[permissions]
- 简而言之,auth与digest的区别就是,前者明文后者密文 setAcl/path auth:lee:lee:cdrwa 与 setAcl/path digest:lee:BASE64(SHA1(password))cdrwa是等价的,在通过addauth digest lee:lee 后都能操作指定节点的权限
- ip:当设置为ip指定的ip地址,此时限制ip进行访问,比如ip:192.168.1.1:[permissions]
- super:代表超级管理员,拥有所有的权限
ACL的构成三- permissions
权限字符串缩写crdwa
- CREATE:创建子节点
- READ:获取节点/子节点
- WRITE:设置节点数据
- DELETE:删除子节点
- ADMIN:设置权限
ACL命令行学习一
- world:anyone:cdrwa
此时没有给予d-删除权限
[zk: localhost:2181(CONNECTED) 12] setAcl /imooc/abc world:anyone:crwa
[zk: localhost:2181(CONNECTED) 13] getAcl /imooc/abc
'world,'anyone
: crwa
删除该节点下的子节点,没有权限
[zk: localhost:2181(CONNECTED) 17] delete /imooc/abc/xyz
Authentication is not valid : /imooc/abc/xyz
权限命令
- auth:user:pwd:cdrwa
- digest:user:BASE64(SHA1(pwd)):cdrwa
- addauth digest user:pwd
- ip:192.168.1.1:cdrwa
需要先注册
[zk: localhost:2181(CONNECTED) 32] setAcl /names/immoc auth:imooc:imooc:cdrwa
Acl is not valid : /names/immoc
[zk: localhost:2181(CONNECTED) 33] addauth digest imooc:imooc
[zk: localhost:2181(CONNECTED) 34] setAcl /names/immoc auth:imooc:imooc:cdrwa
注册完查看权限和密码
[zk: localhost:2181(CONNECTED) 36] getAcl /names/immoc
'digest,'imooc:XwEDaL3J0JQGkRQzM0DpO6zMzZs=
: cdrwa
设置完 在设置其他账户还是第一次设置的用户名和密码 只能设置权限
[zk: localhost:2181(CONNECTED) 37] setAcl /names/immoc auth:xxx:123:cdrwa
[zk: localhost:2181(CONNECTED) 38] getAcl /names/immoc
'digest,'imooc:XwEDaL3J0JQGkRQzM0DpO6zMzZs=
: cdrwa
退出后需要重新登录
setAcl /names/test digest:imooc:XwEDaL3J0JQGk
[zk: localhost:2181(CONNECTED) 13] getAcl /names/test
Authentication is not valid : /names/test
[zk: localhost:2181(CONNECTED) 14] addauth digest imooc:imooc
[zk: localhost:2181(CONNECTED) 15] get /names/test
ttt
ip控制权限
[zk: localhost:2181(CONNECTED) 14] setAcl /test-ip ip:127.0.0.1:cdrwa
[zk: localhost:2181(CONNECTED) 15] getAcl /test-ip
'ip,'127.0.0.1
: cdrwa
ACL命令行学习二
ip限制,忘记用户密码 可以使用super
Super
- 修改zkServer.sh增加super管理员
- 重启zkServer.sh
那么打开zk目录下的/bin/zkServer.sh服务器脚本文件,找到如下一行:
nohup $JAVA "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}"
这就是脚本中启动zk的命令,默认只有以上两个配置项,我们需要加一个超管的配置项:
这个密码是之前登陆的密码,配置一下
-Dzookeeper.DigestAuthenticationProvider.superDigest=用户名:密码
"-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs="
重启登陆
addauth digest super:admin
ACL的常用使用场景
- 开发/测试环境分离,开发者无权操作测试库的节点,只能看
- 生产环境上控制指定ip的服务可以访问相关节点,防止混乱
zk四字命令Four Letter Words
- zk可以通过它自身提供的简写命令来和服务器进行交互
- 需要使用到nc命令,安装:yum install nc
- echo [commond] | nc [ip] [port]
命令一
- [stat] 查看zk的状态信息,以及是否mode 是集群还是单机
[root@cheng bin]# echo stat |nc localhost 2181
Zookeeper version: 3.5.7-f0fdd52973d373ffd9c86b81d99842dc2c7f660e, built on 02/10/2020 11:30 GMT
Clients:
/127.0.0.1:40934[0](queued=0,recved=1,sent=0)
Latency min/avg/max: 0/0/0
Received: 1
Sent: 0
Connections: 1
Outstanding: 0
Zxid: 0x5c
Mode: standalone
Node count: 14
- [ruok] 查看当前zkServer是否启动,返回imok
[root@cheng bin]# echo ruok |nc localhost 2181
imok[root@cheng bin]#
- [dump]列出未经处理的会话和临时节点
[root@cheng bin]# echo dump |nc localhost 2181
SessionTracker dump:
Session Sets (0)/(0):
ephemeral nodes dump:
Sessions with Ephemerals (0):
Connections dump:
Connections Sets (1)/(1):
1 expire at Tue Apr 28 16:34:00 CST 2020:
ip: /127.0.0.1:40988 sessionId: 0x0
命令二
- [conf] 查看服务器配置
[root@cheng bin]# echo conf |nc localhost 2181
clientPort=2181
secureClientPort=-1
dataDir=/usr/dev-environment/zk/dataDir/version-2
dataDirSize=67108880
dataLogDir=/usr/dev-environment/zk/dataLogDir/version-2
dataLogSize=1821
tickTime=2000
maxClientCnxns=60
minSessionTimeout=4000
maxSessionTimeout=40000
serverId=0
- [cons] 展示连接到服务器的客户端信息
[root@cheng bin]# echo cons |nc localhost 2181
/127.0.0.1:41076[0](queued=0,recved=1,sent=0)
- [envi] 环境变量
命令三
- [mntr] 监控zk健康信息
- [wchs] 展示watch的信息
[root@cheng bin]# echo wchs |nc localhost 2181
0 connections watching 0 paths
Total watches:0
- [wchc] 与 [wchp] session与watch及path与watch信息
zk集群搭建
- zk 集群,主从节点,心跳机制(选举模式)
注意点
- 配置数据文件 myid 1/2/3 对应server.1/2/3
- 通过 ./zkCli.sh -server [ip]:[port] 检测集群是否配置成功
zk真实环境搭建
- 需要注意:环境变量的配置,ip配置不同,端口号可以相同
配置zoo.cfg
server.1=192.168.80.94:2888:3888
server.2=192.168.80.95:2888:3888
server.3=192.168.80.96:2888:3888
server后的数字是选举id,在选举过程中会用到。注意:数字一定要能比较出大小。
注意:真实云服务器环境 一定要记得开放ip后面的端口
2888 端口原子广播端口,可以自定义 3888 端口选举端口,可以自定义 在zk安装目录下创建tmp文件,创建myid文件(名字固定),
主节点机器宕机后剩下两台会进行重新选举,恢复后还是属于从节点
并编辑当前虚拟机的选举id Mkdir /usr/soft/zookeeper-3.4.7/tmp tmp#vim myid (内容为1)
zooKeeper原生java api使用
- 会话连接与恢复
- 节点的增删改查
- watch与acl的相关操作
增加超级管理员,防止节点权限密码忘记
- 代码里执行计算值,这个值到时需要配置 super:账户名 admin:密码 (账户名和密码可以自定义)
String hashStr = DigestAuthenticationProvider.generateDigest("super:admin");
System.out.println(hashStr);
//得到的值为:super:xQJmxLMiHGwaqBvst5y6rkB6HQs=
- 去zk服务器中 配置 ,执行命令
vim zkServer.sh
找到如下 nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}"
在其后面追加 =号后面就是上面生成的值
"-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs="
nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" \
"-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
"-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs=" \
-XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \
-cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
保存,重启服务
zkServer.sh restart
在zk客户端命令行行执行
addauth digest super:admin