zookeeper入门(1)「建议收藏」

2022-09-21 21:00:14 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

zookeeper

  • 应用场景
  • zookeeper特点
  • zookeeper数据模型
  • Ubuntu配置
  • zookeeper基本命令

zookeeper是一个典型的分布式数据一致性解决方案,致力于为分布式应用提供一个高性能,高可用,且具有严格顺序访问控制能力的分布式协调存储服务

应用场景

  • 维护配置信息
  • 分布式锁服务
  • 集群管理
  • 生成分布式唯一ID

维护配置信息 如java编程经常遇到配置项,比如数据路连接的url,password等等。通常这些配置文件需要放在服务器上,但需要更改配置文件的时候需要去服务器上更改。但是随着分布式系统的兴起,由于许多服务器都有配置文件,一台台的更改配置文件相当麻烦,因此需要一种服务,能够高效且可靠的完成配置项的更改等操作,并保证各配置项在每台服务器上的一致性。所以有必要将zookeeper当成所有集群的一个配置中心,当zookeeper中过的配置发生变华的时候,会通知集群中的服务器重新获取最新的配置信息。 分布式锁 分布式环境中,一个服务可能部署在多台机器上,一个调用也可能设计多台机器多个进程,zookeeper提供了一种临时有序节点机制,可以生成分布式锁,进而保证分布式环境下的数据一致性。 集群管理 一个集群中的某些服务器宕机或者加入到该集群时,zookeeper会将这些消息通知给集群中的其他服务器,以调整存储和计算等任务的分配和执行等,此外zookeeper还会对故障的服务器做出诊断并尝试修复 生成分布式ID 在过去的单表单库型系统中,通常可以使用数据库字段自带的AUTO_INCREMENT属性来属性来唯一标识一条记录。此时我们就可以用zookeeper在分布式环境下生成全局唯一ID。做法如下:每次要生成一个新的id时,创建一个持久顺序节点,创建操作返回的节点序号,然后把比自己节点小的删除即可。

zookeeper特点

  • 高性能:将全局变量存储在内存中,并直接服务于客户端的所有非事务请求,尤其适用于以读为主的应用场景
  • 高可用:zookeeper一般以集群的方实向外提供服务,一般3-5台机器就可以组成一个可用的zookeeper集群了。每台机器都会在内存中维护当前的服务器状态,并且每台机器之间都会互相保持通信。只要集群中超过一半的机器能工作,那么整个集群就能够正常对外服务。
  • 严格顺序访问:针对于客户端每个请求,zookeeper都会顺序处理

zookeeper数据模型

Zookeeper数据模型类似Linux操作系统的文件系统,也是以树的形式来存储。严格来说是一颗多叉树,每个节点上都可以存储数据,每个节点还可以拥有N个子结点,最上层是根节点以“/”来代表。

 在每个结点上都存储了相应的数据,数据可以是字符串、二进制数。但是默认情况下每个结点的数据大小的上限是1M,这是因为Zookeeper主要是用来协调服务的,而不是存储数据,管理一些配置文件和应用列表之类的数据。虽然可以修改配置文件来改变数据大小的上限,但是为了服务的高效和稳定,建议结点数据不要超过默认值。

节点状态的stat属性

  • cZxid = 0x0 //节点创建时的事务id
  • ctime = Thu Jan 01 08:00:00 CST 1970 //节点创建时间
  • mZxid = 0x0 //节点最近一次更新时的zxid
  • mtime = Thu Jan 01 08:00:00 CST 1970 //节点最近一次更新的时间
  • pZxid = 0x2c //子节点的id
  • cversion = 10 //子节点数据更新次数
  • dataVersion = 0 //本节点数据更新次数
  • aclVersion = 0 //节点ACL(授权信息)的更新次数
  • ephemeralOwner = 0x0 //如果该节点为临时节点,ephemeralOwner值表示与该节点绑定的session id. 如果该节点不是临时节点,ephemeralOwner值为0(临时节点当和客户端会话结束的时候就会销毁,临时节点不允许有子节点)
  • dataLength = 0 //节点数据长度,本例中为hello world的长度
  • numChildren = 10 //子节点个数

Ubuntu配置

  1. 解压下载好的tar.gz安装包到某个目录下,可使用命令:
代码语言:javascript复制
tar -zxvf zookeeper-3.5.4-beta.tar.gz
  1. 进入解压目录的conf目录,复制配置文件zoo_sample.cfg并命名为zoo.cfg,相关命令为:
代码语言:javascript复制
cp zoo_sample.cfg zoo.cfg
  1. 编辑zoo.cfg文件
代码语言:javascript复制
vi zoo.cfg
# 增加dataDir和dataLogDir目录,目录自己创建并指定,用作数据存储目录和日志文件目录
dataDir=/home/local/zk/data
dataLogDir=/home/local/zk/logs
  1. 开启服务
代码语言:javascript复制
# 启动
# 启动ZK服务 
zkServer.sh start
# 查看ZK服务状态 
zkServer.sh status
# 停止ZK服务 
zkServer.sh stop
# 重启ZK服务 
zkServer.sh restart

zookeeper基本命令

ls 查看

代码语言:javascript复制
[zk: localhost:2181(CONNECTED) 1] ls /
[niocoder, zookeeper]
[zk: localhost:2181(CONNECTED) 2] ls /zookeeper 
[quota]
[zk: localhost:2181(CONNECTED) 4] ls /zookeeper/quota
[]

stat 获得节点的更新信息

代码语言:javascript复制
[zk: localhost:2181(CONNECTED) 8] stat /zookeeper
cZxid = 0x0
ctime = Thu Jan 01 00:00:00 UTC 1970
mZxid = 0x0
mtime = Thu Jan 01 00:00:00 UTC 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1

ls2 ls命令和stat命令的整合

代码语言:javascript复制
[zk: localhost:2181(CONNECTED) 10] ls2 /zookeeper
[quota]
cZxid = 0x0
ctime = Thu Jan 01 00:00:00 UTC 1970
mZxid = 0x0
mtime = Thu Jan 01 00:00:00 UTC 1970
pZxid = 0x0
cversion = -1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
[zk: localhost:2181(CONNECTED) 11] 

create 创建节点 create [-s] [-e] path data acl (-e 创建临时节点)(-s 创建顺序节点 自动累加)

代码语言:javascript复制
#创建merryyou节点,节点的内容为merryyou
[zk: localhost:2181(CONNECTED) 1] create /merryyou merryyou
Created /merryyou
#获得merryyou节点内容
[zk: localhost:2181(CONNECTED) 3] get /merryyou
merryyou
cZxid = 0x200000004
ctime = Sat Jun 02 14:20:06 UTC 2018
mZxid = 0x200000004
mtime = Sat Jun 02 14:20:06 UTC 2018
pZxid = 0x200000004
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0

set path data [version] 修改节点(注意乐观锁)

代码语言:javascript复制
[zk: localhost:2181(CONNECTED) 6] get /merryyou
merryyou
cZxid = 0x200000004
ctime = Sat Jun 02 14:20:06 UTC 2018
mZxid = 0x200000004
mtime = Sat Jun 02 14:20:06 UTC 2018
pZxid = 0x200000009
cversion = 4
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 2
# 修改节点内容为new-merryyou
[zk: localhost:2181(CONNECTED) 7] set /merryyou new-merryyou
cZxid = 0x200000004
ctime = Sat Jun 02 14:20:06 UTC 2018
mZxid = 0x20000000a
mtime = Sat Jun 02 14:29:23 UTC 2018
pZxid = 0x200000009
cversion = 4
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 12
numChildren = 2
#再次查询,节点内容已经修改
[zk: localhost:2181(CONNECTED) 8] get /merryyou
new-merryyou
cZxid = 0x200000004
ctime = Sat Jun 02 14:20:06 UTC 2018
mZxid = 0x20000000a
mtime = Sat Jun 02 14:29:23 UTC 2018
pZxid = 0x200000009
cversion = 4
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 12
numChildren = 2
#set 根据版本号更新 dataVersion 乐观锁
[zk: localhost:2181(CONNECTED) 9] set /merryyou test-merryyou 1
cZxid = 0x200000004
ctime = Sat Jun 02 14:20:06 UTC 2018
mZxid = 0x20000000b
mtime = Sat Jun 02 14:31:30 UTC 2018
pZxid = 0x200000009
cversion = 4
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 13
numChildren = 2
#因为数据的版本号已经修改为2 再次使用版本号1修改节点提交错误
[zk: localhost:2181(CONNECTED) 10] set /merryyou test-merryyou 1
version No is not valid : /merryyou
代码语言:javascript复制
[zk: localhost:2181(CONNECTED) 13] delete /merryyou/sec000000000

sec0000000001   sec0000000002
[zk: localhost:2181(CONNECTED) 13] delete /merryyou/sec0000000001
[zk: localhost:2181(CONNECTED) 14] ls /merryyou
[sec0000000002]
[zk: localhost:2181(CONNECTED) 15] 
#版本号操作与set类似 version

delete path [version] 删除节点

代码语言:javascript复制
[zk: localhost:2181(CONNECTED) 13] delete /merryyou/sec000000000

sec0000000001   sec0000000002
[zk: localhost:2181(CONNECTED) 13] delete /merryyou/sec0000000001
[zk: localhost:2181(CONNECTED) 14] ls /merryyou
[sec0000000002]
[zk: localhost:2181(CONNECTED) 15] 
#版本号操作与set类似 version

watcher通知机制 关于watcher机制大体的理解可以为,当每个节点发生变化,都会触发watcher事件,类似于mysql的触发器。zk中 watcher是一次性的,触发后立即销毁。

  • stat path [watch] 设置watch事件
  • get path [watch]设置watch事件
  • 子节点创建和删除时触发watch事件,子节点修改不会触发该事件

stat path [watch] 设置watch事件

代码语言:javascript复制
#添加watch 事件
[zk: localhost:2181(CONNECTED) 18] stat /longfei watch
Node does not exist: /longfei
#创建longfei节点时触发watcher事件
[zk: localhost:2181(CONNECTED) 19] create /longfei test

WATCHER::

WatchedEvent state:SyncConnected type:NodeCreated path:/longfei
Created /longfei

get path [watch] 设置watch事件

代码语言:javascript复制
#使用get命令添加watch事件
[zk: localhost:2181(CONNECTED) 20] get /longfei watch
test
cZxid = 0x20000000e
ctime = Sat Jun 02 14:43:15 UTC 2018
mZxid = 0x20000000e
mtime = Sat Jun 02 14:43:15 UTC 2018
pZxid = 0x20000000e
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
#修改节点触发watcher事件
[zk: localhost:2181(CONNECTED) 21] set /longfei new_test

WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/longfei
cZxid = 0x20000000e
ctime = Sat Jun 02 14:43:15 UTC 2018
mZxid = 0x20000000f
mtime = Sat Jun 02 14:45:06 UTC 2018
pZxid = 0x20000000e
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0
[zk: localhost:2181(CONNECTED) 22] 
#删除触发watcher事件
[zk: localhost:2181(CONNECTED) 23] get /longfei watch
new_test
cZxid = 0x20000000e
ctime = Sat Jun 02 14:43:15 UTC 2018
mZxid = 0x20000000f
mtime = Sat Jun 02 14:45:06 UTC 2018
pZxid = 0x20000000e
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0
[zk: localhost:2181(CONNECTED) 24] delete /longfei

WATCHER::

WatchedEvent state:SyncConnected type:NodeDeleted path:/longfei
[zk: localhost:2181(CONNECTED) 25] 

ACL权限控制 ZK的节点有5种操作权限:CREATE、READ、WRITE、DELETE、ADMIN 也就是 增、删、改、查、管理权限,这5种权限简写为crwda(即:每个单词的首字符缩写)。 注:这5种权限中,delete是指对子节点的删除权限,其它4种权限指对自身节点的操作权限

身份的认证有4种方式:

  • world:默认方式,相当于全世界都能访问
  • auth:代表已经认证通过的用户(cli中可以通过addauth digest user:pwd 来添加当前上下文中的授权用户)
  • digest:即用户名:密码这种方式认证,这也是业务系统中最常用的
  • ip:使用Ip地址认证

getAcl:获取某个节点的acl权限信息

代码语言:javascript复制
#获取节点权限信息默认为 world:cdrwa任何人都可以访问
[zk: localhost:2181(CONNECTED) 34] getAcl /merryyou
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 35] 

setAcl 设置权限

代码语言:javascript复制
[zk: localhost:2181(CONNECTED) 35] create /merryyou/test test
Created /merryyou/test
[zk: localhost:2181(CONNECTED) 36] getAcl /merryyou/test
'world,'anyone
: cdrwa
#设置节点权限 crwa 不允许删除
[zk: localhost:2181(CONNECTED) 37] setAcl /merryyou/test world:anyone:crwa
cZxid = 0x200000018
ctime = Sat Jun 02 16:18:18 UTC 2018
mZxid = 0x200000018
mtime = Sat Jun 02 16:18:18 UTC 2018
pZxid = 0x200000018
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
#查询刚才设置的acl权限信息 crwa 没有删除权限
[zk: localhost:2181(CONNECTED) 38] getAcl /merryyou/test
'world,'anyone
: crwa
[zk: localhost:2181(CONNECTED) 39] 
[zk: localhost:2181(CONNECTED) 39] create /merryyou/test/abc abc
Created /merryyou/test/abc
#删除子节点的时候提交权限不足
[zk: localhost:2181(CONNECTED) 40] delete /merryyou/test/abc
Authentication is not valid : /merryyou/test/abc
#设置节点的权限信息为rda
[zk: localhost:2181(CONNECTED) 41] setAcl /merryyou/test world:anyone:rda 
cZxid = 0x200000018
ctime = Sat Jun 02 16:18:18 UTC 2018
mZxid = 0x200000018
mtime = Sat Jun 02 16:18:18 UTC 2018
pZxid = 0x20000001a
cversion = 1
dataVersion = 0
aclVersion = 2
ephemeralOwner = 0x0
dataLength = 4
numChildren = 1
[zk: localhost:2181(CONNECTED) 42] getAcl /merryyou/test
'world,'anyone
: dra
#可以成功删除
[zk: localhost:2181(CONNECTED) 43] delete /merryyou/test/abc             
[zk: localhost:2181(CONNECTED) 46] ls /merryyou/test
[]
[zk: localhost:2181(CONNECTED) 47] 
#设置节点信息为a admin
[zk: localhost:2181(CONNECTED) 47] setAcl /merryyou/test world:anyone:a  
cZxid = 0x200000018
ctime = Sat Jun 02 16:18:18 UTC 2018
mZxid = 0x200000018
mtime = Sat Jun 02 16:18:18 UTC 2018
pZxid = 0x20000001d
cversion = 2
dataVersion = 0
aclVersion = 3
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
#获取 设置都提示权限不足
[zk: localhost:2181(CONNECTED) 49] get /merryyou/test
Authentication is not valid : /merryyou/test
[zk: localhost:2181(CONNECTED) 50] set /merryyou/test 123
Authentication is not valid : /merryyou/test
[zk: localhost:2181(CONNECTED) 51] 

acl Auth 密码明文设置

代码语言:javascript复制
[zk: localhost:2181(CONNECTED) 53] create /niocoder/merryyou merryyou
Created /niocoder/merryyou
#查询默认节点权限信息
[zk: localhost:2181(CONNECTED) 54] getAcl /niocoder/merryyou
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 55] 
#使用auth设置节点权限信息
[zk: localhost:2181(CONNECTED) 2] setAcl /niocoder/merryyou auth:test:test:cdrwa  
Acl is not valid : /niocoder/merryyou
# 注册test:test 账号密码
[zk: localhost:2181(CONNECTED) 3] addauth digest test:test
[zk: localhost:2181(CONNECTED) 4] setAcl /niocoder/merryyou auth:test:test:cdrwa
cZxid = 0x200000020
ctime = Sat Jun 02 16:32:08 UTC 2018
mZxid = 0x200000020
mtime = Sat Jun 02 16:32:08 UTC 2018
pZxid = 0x200000020
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0
#查询节点权限信息 密码为密文格式
[zk: localhost:2181(CONNECTED) 5] getAcl /niocoder/merryyou
'digest,'test:V28q/NynI4JI3Rk54h0r8O5kMug=
: cdrwa
[zk: localhost:2181(CONNECTED) 6] 

acl digest 密码密文设置

代码语言:javascript复制
[zk: localhost:2181(CONNECTED) 13] create /names test
Created /names
[zk: localhost:2181(CONNECTED) 14] getAcl /names
'world,'anyone
: cdrwa
#使用digest设置节点的权限信息 密码为test密文
[zk: localhost:2181(CONNECTED) 15] setAcl /names digest:test:V28q/NynI4JI3Rk54h0r8O5kMug=:cdra
cZxid = 0x400000006
ctime = Sun Jun 03 01:01:17 UTC 2018
mZxid = 0x400000006
mtime = Sun Jun 03 01:01:17 UTC 2018
pZxid = 0x400000006
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
#查询节点权限信息
[zk: localhost:2181(CONNECTED) 16] getAcl /names
'digest,'test:V28q/NynI4JI3Rk54h0r8O5kMug=
: cdra
#获取节点信息提示权限不足
[zk: localhost:2181(CONNECTED) 5] get /names
Authentication is not valid : /names
# 注册账户
[zk: localhost:2181(CONNECTED) 4] addauth digest test:test
# 可以正常获取
[zk: localhost:2181(CONNECTED) 17] get /names          
test
cZxid = 0x400000006
ctime = Sun Jun 03 01:01:17 UTC 2018
mZxid = 0x400000006
mtime = Sun Jun 03 01:01:17 UTC 2018
pZxid = 0x400000006
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
#由于没有设置写权限不能修改节点 w
[zk: localhost:2181(CONNECTED) 18] set /names 111
Authentication is not valid : /names
[zk: localhost:2181(CONNECTED) 19] delete /names
[zk: localhost:2181(CONNECTED) 20] 

acl ip 控制客户端

代码语言:javascript复制
[zk: localhost:2181(CONNECTED) 22] create /niocoder/ip aa
Created /niocoder/ip
[zk: localhost:2181(CONNECTED) 23] get /niocoder/ip
aa
cZxid = 0x40000000a
ctime = Sun Jun 03 01:06:47 UTC 2018
mZxid = 0x40000000a
mtime = Sun Jun 03 01:06:47 UTC 2018
pZxid = 0x40000000a
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 2
numChildren = 0
# 添加ip控制的权限信息
[zk: localhost:2181(CONNECTED) 24] setAcl /niocoder/ip ip:192.168.0.68:cdrwa
cZxid = 0x40000000a
ctime = Sun Jun 03 01:06:47 UTC 2018
mZxid = 0x40000000a
mtime = Sun Jun 03 01:06:47 UTC 2018
pZxid = 0x40000000a
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 2
numChildren = 0
[zk: localhost:2181(CONNECTED) 25] getAcl /niocoder/ip
'ip,'192.168.0.68
: cdrwa
[zk: localhost:2181(CONNECTED) 26] 

acl super超级管理员 使用super权限需要修改zkServer.sh,添加super管理员,重启zkServer.sh

代码语言:javascript复制
"-Dzookeeper.DigestAuthenticationProvider.superDigest=test:V28q/NynI4JI3Rk54h0r8O5kMug="
 nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" "-Dzookeeper.DigestAuthenticationprovider.superDigest=test:V28q/NynI4JI3Rk54h0r8O5kMug=" 
    -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &

#重启进入zkCli
#由于之前设置ip权限,所以不允许访问
[zk: localhost:2181(CONNECTED) 2] ls /niocoder/ip
Authentication is not valid : /niocoder/ip
#登录账号信息,即为管理员账号
[zk: localhost:2181(CONNECTED) 3] addauth digest test:test
#正常访问,节点内容为空
[zk: localhost:2181(CONNECTED) 4] ls /niocoder/ip
[]
[zk: localhost:2181(CONNECTED) 5] get /niocoder/ip
aa
cZxid = 0x40000000a
ctime = Sun Jun 03 01:06:47 UTC 2018
mZxid = 0x40000000a
mtime = Sun Jun 03 01:06:47 UTC 2018
pZxid = 0x40000000a
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 2
numChildren = 0
[zk: localhost:2181(CONNECTED) 6] 

acl super超级管理员 使用super权限需要修改zkServer.sh,添加super管理员,重启zkServer.sh

代码语言:javascript复制
"-Dzookeeper.DigestAuthenticationProvider.superDigest=test:V28q/NynI4JI3Rk54h0r8O5kMug="
 nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" "-Dzookeeper.DigestAuthenticationprovider.superDigest=test:V28q/NynI4JI3Rk54h0r8O5kMug=" 
    -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &

#重启进入zkCli
#由于之前设置ip权限,所以不允许访问
[zk: localhost:2181(CONNECTED) 2] ls /niocoder/ip
Authentication is not valid : /niocoder/ip
#登录账号信息,即为管理员账号
[zk: localhost:2181(CONNECTED) 3] addauth digest test:test
#正常访问,节点内容为空
[zk: localhost:2181(CONNECTED) 4] ls /niocoder/ip
[]
[zk: localhost:2181(CONNECTED) 5] get /niocoder/ip
aa
cZxid = 0x40000000a
ctime = Sun Jun 03 01:06:47 UTC 2018
mZxid = 0x40000000a
mtime = Sun Jun 03 01:06:47 UTC 2018
pZxid = 0x40000000a
cversion = 0
dataVersion = 0
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 2
numChildren = 0
[zk: localhost:2181(CONNECTED) 6] 

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/168797.html原文链接:https://javaforall.cn

0 人点赞