zookeeper几个关键的东西:
1.数据结构-节点 /a/b/c 节点 包含了目录和文件的特性(名称类似目录,本身又类似文件携带数据)
2.节点分类:永久/临时|有序/无须
特点一:节点的创建必须一级一级的创建,如创建/a/b节点,需要先创建/a节点,再创建/a/b节点
特点二:节点的创建只能创建不存在的节点,不能重复,如已创建/a节点,再次创建/a节点会失败
特点三:有序节点的创建为自动赋予序号,如创建/a,实际创建的是/a00000001,这个序号是递增的,再创建/b,实际创建的是/b0000002,再次创建/a,实际创建的是/a0000003(临时节点的创建可以多次创建/a,因为实际创建的是/a+序号,没有重复)
特点四:每个节点都有版本号,新增时版本号为0,没有修改版本号递增
3.全局事务id,zk集群中,所有的写操作,leader都会生成一个有序的事务id,事务的执行是按照事务id的顺序来执行的
4.watcher:zk具有监控功能,可以监控节点的数据变化和节点删除,还可以监控子节点的增加和删除
5.zab协议:leader选举、恢复同步、原子广播-----保证了zk集群数据的一致性
1.Zookeeper常用的业务场景
zookeeper是一个分布式的数据一致性的解决方案。致力于为分布式应用一同一个高性能、高可用,且具有严格顺序访问控制能力的分布式协调存储服务。
维护配置信息
分布式锁服务(临时有序节点)
集群管理
分布式唯一id(持久化有序节点)
1.1维护配置信息
把zookeeper作为一个配置中心

1.3集群管理

[zk: localhost:2181(CONNECTED) 7] get /ns-1/tenant
cZxid = 0x6a0000000a ctime = Wed Mar 27 09:56:44 CST 2019 mZxid = 0x6a0000000a mtime = Wed Mar 27 09:56:44 CST 2019 pZxid = 0x6a0000000e cversion = 2 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 0 numChildren = 2
useradd zookeeper passwd zookeeper//解压jdk tar -xzvf jdk-8u131-linux-x64.tar.gz
// vim打开 .bash_profile文件 vi .bash_profile // 文件中加入如下内容 JAVA_HOME=/home/zookeeper/jdk1.8.0_131 export JAVA_HOME PATH=$JAVA_HOME/bin:$PATH export PATH // 使环境变量生效 . .bash_profile
// 敲如下命令,系统如图反馈说明安装成功 java -version

// 解压zookeeper tar -xzvf apache-zookeeper-3.6.2.tar.gz
// 进入conf目录
cd /usr/local/programs/zookeeper/apache-zookeeper-3.6.2/conf
// 修改配置文件前先复制一份配置文件
cp zoo_sample.cfg zoo.cfg
// zookeeper根目录下新建data目录 -用于存放数据
mkdir data
// vi 修改配置文件中的dataDir
// 此路径用于存储zookeeper中数据的内存快照、及事物日志文件
dataDir=/usr/local/programs/zookeeper/apache-zookeeper-3.6.2/data
配置文件名称改为 zoo.cfg

4.7.新版 ZooKeeper 启动时一直报: Starting zookeeper … FAILED TO START
(https://blog.csdn.net/peng2hui1314/article/details/107255142)
以下几种情况
1. 下载的版本问题(>= 3.5.5)
2. 端口冲突问题(>=3.5.0)
4.7.1. 下载的版本问题(>= 3.5.5)
版本:3.6.1,实际上只要 >= 3.5.5 版本都会出现这种问题。
问题原因:下载了错误的版本文件,Zookeeper 从3.5.5后开始拆分为两个版本,而且他们的结构还很类似。
标准版本(Apache ZooKeeper x.y.z ),下载的文件名为:apache-zookeeper-x.y.z-bin.tar.gz
另一个是源码版本(Apache ZooKeeper x.y.z Source Release),下载的文件名为:apache-zookeeper-x.y.z.tar.gz
官方说明:
在这里插入图片描述
所以下载 Zookeeper 的时候要注意,应该下载第一个。
在这里插入图片描述
4.7.2. 端口冲突问题(可能遇到)
在3.5.5版本及以上,Zookeeper 提供了一个内嵌的Jetty容器来运行 AdminServer,默认占用的是 8080端口,AdminServer 主要是来查看 Zookeeper 的一些状态,如果机器上有其他程序(比如:Tomcat)占用了 8080 端口,也会导致 Starting zookeeper … FAILED TO START 的问题。
官网 AdminServer 文档地址
该问题的错误日志如下:
org.apache.zookeeper.server.admin.AdminServer$AdminServerException: Problem starting AdminServer on address 0.0.0.0, port 8080 and command URL /commands at org.apache.zookeeper.server.admin.JettyAdminServer.start(JettyAdminServer.java:176) at org.apache.zookeeper.server.ZooKeeperServerMain.runFromConfig(ZooKeeperServerMain.java:153) at org.apache.zookeeper.server.ZooKeeperServerMain.initializeAndRun(ZooKeeperServerMain.java:112) at org.apache.zookeeper.server.ZooKeeperServerMain.main(ZooKeeperServerMain.java:67) at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:140) at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:90) Caused by: java.io.IOException: Failed to bind to /0.0.0.0:8080 //不能绑定8080端口 at org.eclipse.jetty.server.ServerConnector.openAcceptChannel(ServerConnector.java:346) at org.eclipse.jetty.server.ServerConnector.open(ServerConnector.java:307) at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:80) at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:231) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72) at org.eclipse.jetty.server.Server.doStart(Server.java:385) at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:72) at org.apache.zookeeper.server.admin.JettyAdminServer.start(JettyAdminServer.java:167) ... 5 more Caused by: java.net.BindException: Address already in use //地址正在被使用 at sun.nio.ch.Net.bind0(Native Method) at sun.nio.ch.Net.bind(Net.java:433) at sun.nio.ch.Net.bind(Net.java:425) at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223) at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74) at org.eclipse.jetty.server.ServerConnector.openAcceptChannel(ServerConnector.java:342) ... 12 more Unable to start AdminServer, exiting abnormally 2020-07-17 21:07:30,759 [myid:] - INFO [main:ZKAuditProvider@42] - ZooKeeper audit is disabled. 2020-07-17 21:07:30,760 [myid:] - ERROR [main:ServiceUtils@42] - Exiting JVM with code 4
可以通过以下几种方式去解决:
如果不需要 AdminServer ,可以直接禁用:打开 zoo.cfg 配置文件,直接添加以下语句即可。
# 禁用 AdminServer 服务
admin.enableServer=false
如果想使用 AdminServer , 那么可以直接在 zoo.cfg 配置文件中修改端口号即可,比如让其绑定 9000。
# admin port
admin.serverPort=9000
5.常用操作命令
5.1基础命令
./zkServer.sh start 启动zookeeper
./zkServer.sh status 查看zookeeper状态
./zkCli.sh 启动客户端进入会话
quit 结束当前会话- 也就是 ./zkCli.sh的会话结束了,需要重新./zkCli.sh新建会话
5.2创建节点
create
create 命令用于创建节点并赋值
格式:create [-s] [-e] path data acl
[-s] [-e]:-s 和 -e 都是可选的,-s 代表顺序节点, -e 代表临时节点,注意其中 -s 和 -e 可以同时使用的,并且临时节点不能再创建子节点。也就是不设置-s和-e时,创建的是持久化的无序节点
path:指定要创建节点的路径,比如 /runoob
data:要在此节点存储的数据
acl:可选,访问权限相关,默认是 world,相当于全世界都能访问
创建持久化无序节点
创建持久化有序节点,这里没有设置data,也就是null。有序节点的路径自动加上了一个序号
创建临时无序节点:临时节点的生命周期是当前会话。quit退出当前会话的话,临时节点会被删除
5.3获取节点的数据
get
格式:get path
获取无序节点
获取有序节点:它的路径自动加上了一个序号
5.4查看节点状态信息
stat
格式:stat path [watch]
path:代表路径。
[watch]:对节点进行事件监听
节点各个属性如下表。其中一个重要的概念是 Zxid(ZooKeeper Transaction
Id-事务id),ZooKeeper 节点的每一次更改都具有唯一的 Zxid,且是递增的,如果 Zxid1 小于 Zxid2,则
Zxid1 的更改发生在 Zxid2 更改之前
ACL是和当前节点的权限的相关的一个属性
5.5修改节点存储的数据
set
格式:set path data [-v version]
path:节点路径
data:需要存储的数据
[version]:可选项,版本号(可用作乐观锁)。从创建一个节点开始,会为这个节点生成一个版本号,从0开始。每次对这个节点进行修改,版本号会+1
不加版本号
加上版本号
通过stat命令,看到当前data版本号时7
这里指定的版本号是15 所以修改失败
这里指定的版本号是7 所以修改成功
5.6删除节点
delete
格式:delete path [-v version]
path:节点路径
[version]:可选项,版本号(同 set 命令)
当前data版本是8
版本错误,删除失败
版本正确,删除成功
再创建一个节点 /hadop/a
此时来删除/hadop,删除失败。也就是说,delete不能删除有子节点的节点
5.7删除节点(可删除带有子节点的节点)
这个命令被deleteall替代,不推荐使用
rmr
格式:rmr path
path:节点路径
5.8删除节点(可删除带有子节点的节点)
deleteall
格式:deleteall path
path:节点路径
5.9查看某个路径下目录列表
ls
格式:ls path
创建/a节点 创建/a/b节点
查看a节点下的目录
再创建节点/a/b/c
查看a节点下的目录,发现还是只有b节点。说明ls只能查看节点的子节点,不能查看子节点下的节点
5.10查看某个路径下目录列表
ls2
格式:ls2 path
ls2命令和ls一样,也是查看节点的子节点,不能查看子节点下的节点,但是信息更加全面
再创建一个节点/a/bb ls2查看
6.监听器
6.1zookeeper 事件监听机制
6.1.1 watcher概念
zookeeper提供了数据的发布/订阅功能,多个订阅者可同时监听某一特定主题对象,当该主题对象的自身状态发生变化时(例如节点内容改变、节点下的子节点列表改变等),会实时、主动通知所有订阅者zookeeper采用了Watcher机制实现数据的发布/订阅功能。该机制在被订阅对象发生变化时会异步通知客户端,因此客户端不必在Watcher注册后轮询阻塞,从而减轻了客户端压力。watcher机制实际上与观察者模式类似,也可看作是一种观察者模式在分布式场景下的实现方式。
6.1.2 watcher架构
Watcher实现由三个部分组成:Zookeeper服务端、Zookeeper客户端、客户端的ZKWatchManager对象
客户端首先将Watcher注册到服务端,同时将Watcher对象保存到客户端的Watch管理器中。当ZooKeeper服务端监听的数据状态发生变化时,服务端会主动通知客户端,接着客户端的Watch管理器会触发相关Watcher来回调相应处理逻辑,从而完成整体的数据发布/订阅流程
6.1.3watch特性
watch是串行化执行的,也就是一个一个的watch执行,串行同步执行。
6.2watch相关命令
6.2.1get
格式:get path [watch] 或者 get [-s] [-w] path
使用 get path [watch] 注册的监听器能够在节点内容发生改变的时候,向客户端发出通知。需要注意的是 zookeeper 的触发器是一次性的 (One-time trigger),即触发一次后就会立即失效
开始监听get path [watch]
另一个客户端修改
此处收到事件通知
开始监听get -w path
另一个客户端修改
此处收到事件通知
6.2.2stat
格式:stat path [watch] 或者 stat [-w] path
使用 stat path [watch] 注册的监听器能够在节点状态发生改变的时候,向客户端发出通知。需要注意的是 zookeeper 的触发器是一次性的 (One-time trigger),即触发一次后就会立即失效
开始监听stat path [watch]
另一个客户端修改
此处收到事件通知
开始监听stat-w path
另一个客户端修改
此处收到事件通知
6.2.3 lsls2 path [watch]
格式:lsls2 path [watch] 或者 lsls2 -w path
使用 ls path [watch] 或 ls2 path [watch] 注册的监听器能够监听该节点下所有子节点的增加和删除操作
6.3监听器的使用
zookeeper可以作为配置中心来使用。监听器就可以对配置内容进行监听。当配置发生变化时,可以收到通知,做相应的处理。
7.ACL权限控制
7.1 概述
zookeeper 类似文件系统,client 可以创建节点、更新节点、删除节点,那么如何做到节点的权限的控制呢?zookeeper的access control list 访问控制列表可以做到这一点。
acl 权限控制,使用scheme:id:permission 来标识,主要涵盖 3 个方面:
权限模式(scheme):授权的策略
授权对象(id):授权的对象
权限(permission):授予的权限
zookeeper的acl权限控制的特性:
zooKeeper的权限控制是基于每个znode节点的,需要对每个节点设置权限
每个znode支持设置多种权限控制方案和多个权限
子节点不会继承父节点的权限,客户端无权访问某节点,但可能可以访问它的子节点
7.2权限模式
采用何种方式授权
world:对所有用户授权(默认的)
ip:对指定ip用户授权
auth:对某个指定用户授权(用户:密码 密码可以是明文的)
digest:对某个指定用户授权(用户:密码 密码必须是加密的)
7.3授权的对象
授权模式使用world:授权对象只有一种:anyone -登录zookeeper的所有人
授权模式使用ip:ip地址
授权模式使用auth:指定的用户
授权模式使用digest:指定的用户
7.4授权的权限
create、delete、read、writer、admin也就是 增、删、改、查、管理权限,这5种权限简写为cdrwa,注意:这5种权限中,delete是指对子节点的删除权限,其它4种权限指对自身节点的操作权限
7.5授权相关命令
- getAcl 命令:获取某个节点的 acl 权限信息。
- setAcl 命令:设置某个节点的 acl 权限信息。
- addauth 命令:输入认证授权信息,注册时输入明文密码,加密形式保存
getAcl - 最开始默认是world:anyone
7.6授权实例
1)world模式
2)ip模式
设置ip权限
远程登录zookeeper命令:./zkCli.sh -server ip
3)auth模式
添加用户(这个操作将用户user1加入了当前会话,当前会话可以访问user1的节点)
设置权限
获取权限
获取数据
qiut退出当前会话后,重新登录,获取数据,权限不足
再次添加用户
4)digest模式
设置权限,需要加上密码,且密码是密文
获取密文(账号user2 密码 user2)
echo -n user2:user2 | openssl dgst -binary -sha1 | openssl base64
结果:ExK4ZEpM5XR9l8dLA7B6b79kLIo=
设置权限(密码是密文)
获取权限,权限不足
添加用户(密码明文)
获取权限
5)多种授权模式
授权,多种授权用逗号隔开
添加用户
获取数据
7.7超级管理员
echo -n super:admin | openssl dgst -binary -sha1 | openssl base64
生成结果
xQJmxLMiHGwaqBvst5y6rkB6HQs
nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}"
"-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}"
-XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p'
这就是脚本中启动zookeeper的命令,默认只有以上两个配置项,我们需要加一个超管的配置项
"- Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBv st5y6rkB6HQs="
那么修改以后这条完整命令变成了
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:xQJmxLMiHGwaqBv
st5y6rkB6HQs="
-XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p'
重启zookeeper ps-ef|grep zookeeper kill - 9 xxx 杀掉进程
之后启动zookeeper
创建节点/www
create /www
设置权限
setAcl /www auth:user3:cdrwa
获取数据,权限不足,添加超级管理员再获取