目录
什么是Zookeeper?
zookeeper的特性
zookeeper的作用
zookeeper的安装
zookeeper的目录结构介绍
zookeeper配置文件zoo_sample.cfg
zookeeper启动
zookeeper基本数据模型
zookeeper的session
zookeeper命令
zookeeper的watcher 机制
触发 watcher 事件
zookeeper的ACL权限
ACL 命令
acl world 示例
acl auth/digest 示例
acl ip 示例
acl super 超级管理员
zookeeper 四字命令
zookeeper 集群
搭建伪分布式集群
搭建真实分布式集群
官网文档:ZooKeeper: Because Coordinating Distributed Systems is a Zoo
什么是Zookeeper?
ZooKeeper是一个集中服务,用于维护配置信息、命名、提供分布式同步和组服务。所有这些类型的服务都以某种形式被分布式应用程序使用。每次实施它们时,都要进行大量的工作来修复不可避免的bug和竞争条件。由于实现这类服务的困难,应用程序最初通常会对它们进行精简,这使得它们在发生变化时变得脆弱,并且难以管理。即使操作正确,在部署应用程序时,这些服务的不同实现也会导致管理复杂性。
ZooKeeper的目标是将这些不同服务的精髓提炼为一个非常简单的接口,从而实现集中式协调服务。服务本身是分布式的,并且高度可靠。共识、组管理和存在协议将由服务实现,因此应用程序不需要自己实现它们。特定于应用程序的这些使用将由Zoo Keeper的特定组件和特定于应用程序的约定的混合组成。
zookeeper的特性
- 顺序一致性:数据按照顺序分批入库
- 原子性:集体更新成功或失败,没有部分结果
- 单一视图:客户端连接集群中的任一zk服务节点,它看到的数据都是相同的。
- 可靠性:每次对zk的操作状态都会保存在服务端
- 实时性:客户端可以读取到zk服务端的最新数据
zookeeper的作用
集群管理
ZooKeeper一般以集群的方式对外提供服务,一般3 ~ 5台机器就可以组成一个可用的Zookeeper集群了,每台机器都会在内存中维护当前的服务器状态,并且每台机器之间都相互保持着通信。只要集群中超过半数的机器能够正常工作,那么整个集群就能够正常对外服务
配置管理
统一配置文件管理,即只需要部署一台服务器,则可以把相同的配置文件同步更新到其他所有服务器中(发布订阅),此操作在云计算中用的特别多(假设修改了redis统一配置)
分布式锁
分布式锁是控制分布式系统或不同系统之间共同访问共享资源的一种锁实现,如果不同的系统或同一个系统的不同主机之间共享了某个资源时,往往需要互斥来防止彼此干扰来保证一致性。
zookeeper的安装
下载地址:https://zookeeper.apache.org/releases.html
注意:需要JDK1.8_u211 以上本版
将下载的 zookeeper 安装包上传到 linux 环境的 /usr/local 目录,进行tar -zxvf 解压缩
配置 zookeeper 环境变量
vim /etc/profile
export ZOOKEEPER_HOME=/usr/local/zookeeper-3.8.0
export PATH=$PATH:$ZOOKEEPER_HOME/bin:$JAVA_HOME/bin
source /etc/profile
zookeeper的目录结构介绍
bin:zookeeper的操作命令目录
conf:存放配置文件,其中我们需要修改zoo_sample.cfg文件
docs:帮助文档目录
lib:依赖jar包目录
zookeeper配置文件zoo_sample.cfg
配置时请 copy 重命名为 zoo.cfg 文件
# 每一次滴答的毫秒数,滴答:zookeeper基本时间单元
tickTime=2000# 初始同步阶段可以执行的滴答数,用于集群,配置主节点等待从节点启动并完成数据同步的时间,以 tickTime 的倍数来表示,默认是10 那么就是 10*tickTime
initLimit=10# 在发送请求和获得确认之间可以经过的滴答数,用于集群,配置 主节点 与 从节点 之间心跳检测的最大时间长度,默认值是 5,也就是 5*tickTime
syncLimit=5# zookeeper服务存储快照目录,必须配置,不能配置在/tmp目录下,该目录下的文件会被自动删除
dataDir=/usr/local/zookeeper-3.8.0/dataDir
# 日志目录,如果不配置会共用dataDir目录
dataLogDir=/usr/local/zookeeper-3.8.0/dataLogDir
# 客户端连接的端口,服务器对外暴露的端口,默认 2181
clientPort=2181
zookeeper启动
进入 zk 的 bin 目录下,使用 ./zkServer.sh start 启动
# 启动 zk,其他参数有 {start|start-foreground|stop|version|restart|status|print-cmd}
./zkServer.sh start
zookeeper基本数据模型
ZooKeeper提供的命名空间非常类似于标准文件系统的名称空间。名称是由斜杠(/)分隔的路径元素序列。ZooKeeper命名空间中的每个节点都由路径标识。
每一个节点都被称之为znode,它可以有子节点,可以有数据(存储数据不宜过大,几K即可)
每个zk节点都有各自的版本号,可以通过命令查看节点信息
每当节点数据发生变化,该节点的版本号会累加(乐观锁)
删除/修改节点时,版本号不匹配会报错(乐观锁version号不一致不让修改)
节点可以设置权限acl(权限控制列表),可以通过权限来限制用户的访问
znode 的 四种类型
- 永久目录节点-PERSISTENT
- 客户端与zookeeper断开连接后,该节点依旧存在
- 永久带顺序编号目录节点-PERSISTENT_SEQUENTIAL
- 客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号。
- 临时目录节点-EPHEMERAL
- 客户端与zookeeper断开连接后,该节点被删除 // 不会立马删除,心跳检测时间到了后,才会被删除
- 临时带顺序编号目录节点-EPHEMERAL_SEQUENTIAL
- 客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号。
zookeeper的session
客户端与服务端之间的连接存在的会话,称之为session。
每个session都可以设置超时时间,超时时间到了后session过期
session过期,则临时节点znode会被zk删除
心跳机制:客户端向服务端发送ping包请求,服务端没有接收到客户端的ping包,会断开客户端连接
zookeeper命令
注意:zk的命令工具,在 zookeeper/bin 目录下
- 启动 zk 服务端
./zkServer.sh start # start:启动,stop:关闭,restart:重启,status:查看zk状态
- 客户端连接服务端
./zkCli.sh # 连接到 localhost:2181 服务端
./zkCli.sh -server 192.168.189.77:2181 # 连接到远程 服务端,指定ip:端口
连接成功后
- ls 命令
作用和 linux 的 ls 命令相似,用于查看指定目录下有哪些节点
ls 有 3 个参数 -s -w -R
-s:查看节点信息,与 stat 命令作用相同
- cZxid:创建节点后zk为此节点分配的节点id
- ctime:节点创建的时间
- mZxid:节点被修改后,zk为此节点分配的节点id
- mtime:节点修改的时间
- pZxid:子节点列表事务id,子节点被修改后此值发生变化,子节点数据被修改后不影响此值
- cversion:子节点的版本号
- dataVersion:当前节点的数据版本号,节点数据被修改后,dataVersion会发生变化
- aclVersion:acl权限版本号
- ephemeralOwner:创建临时节点时的会话 sessionID,如果是持久性节点那么值为 0
- dataLength:数据长度
- numChildren:子节点数量
-w:为节点添加一个监听,节点被修改时,此客户端会收到回调
-R:列出节点下的所有子节点
- create 命令
创建节点 create [-s] [-e] [-c] [-t ttl] path [data] [acl]
create 命令的参数
:不带参数,创建一个永久无序节点
-s:创建永久顺序节点,zk会把节点后面自动带一串数字标识节点顺序
-e:创建临时节点
-c:创建容器节点
-t ttl:创建一个有过期时间的节点,-t 毫秒
path:节点名称/路径
data:节点的数据
acl:节点权限
-s -e:创建临时顺序节点
- get 命令
获取节点数据 // ls 是获取节点,get 是获取节点中的数据
get 命令的参数
-s:查看节点数据,带节点信息
-w:为节点添加一个监听,节点被修改时,此客户端会收到回调
- set 命令
修改节点数据,节点 dataVersion 累加
set 命令的参数
-s:修改节点数据时显示节点信息
-v version:修改节点数据时带上 dataVersion 版本号的值,如果和当前版本号不一致,修改失败
- delete 命令
删除节点,当节点中有子节点时不允许删除 // 有数据时可以删除,有子节点时不可以删除
delete 命令的参数
-v version:删除节点时带上 dataVersion 版本号的值,如果和当前版本号不一致,删除失败
- deleteall 命令
删除节点,包括节点下的所有子节点。
zookeeper的watcher 机制
针对每个节点的操作,都会有一个监督者 watcher
当监控的 znode 发生了变化,则触发 watcher 事件
watcher 是一次性的,触发后立即销毁
不论是父节点还是子节点发生变化,都会触发 watcher
watcher 事件类型:父节点创建事件(NodeCreated)、父节点删除事件(NodeDeleted)、子节点变化(创建、删除)事件(NodeChildrenChanged)、节点数据变化事件(NodeDataChanged)
触发 watcher 事件
- 触发父节点创建事件 NodeCreated
stat -w /test // 查看 /test 节点状态 -w 设置监听,节点不存在也没关系
create /test // 创建节点时,监听触发
- 触发父节点删除事件 NodeDeleted
ls -w /test // 监听节点,为节点本身创建监听
delete /test // 删除节点时,监听触发
- 触发子节点变化(创建删除)事件 NodeChildrenChanged
stat -w /test // 为父节点创建监听
create /test/a // 删除子节点,监听触发
- 触发节点数据变化事件 NodeDataChanged
stat -w /test // 查看 /test 节点状态 -w 设置监听
set /test hello // 修改节点数据,监听触发
修改子节点数据 不触发任何事件,只有在子节点本身上设置watcher监听,修改子节点数才会触发相应事件。
zookeeper的ACL权限
ACL(Access control lists)权限控制。针对节点设置相关读写等权限,目的是为了保障数据安全性。
使用场景:
区分环境,开发环境、测试环境等
ip 白名单,生产环境上只有指定的 ip 才有权访问
acl 通过 [scheme:id:permissions] 构成权限列表
- scheme:代表采用的哪种权限机制
- world:world 下只有一个id,即只有一个用户,也就是anyone,组合写法 world:anyone:[permissions] // 表示所有用户,对节点有操作权限
- auth:代表认证登录,需要注册用户并且有权限才可以访问,存在zk服务中的密码是经过BASE64(SHA1(password))加密的,组合写法 auth:username:password:[permissions]
- digest:代表认证登录,需要对密码加密才能访问,组合写法 digest:username:BASE64(SHA1(password)):[permissions]
- ip:限定指定的ip才可以进行访问,组合写法 ip:192.168.x.x:[permissions]
- super:超级管理员,拥有所有的权限,可以用来在忘记密码或者设置错误权限导致自己无法操作节点时,使用super来重置所有权限或者删除节点
- id:代表允许访问的用户
- permissions:权限组合字符串crdwa,可以指定不同的权限范围和角色
- c:CREATE:创建子节点权限
- r:READ:获取节点/子节点权限 // 读权限
- w:WRITE:设置节点数据权限 // 写权限
- d:DELEETE:删除子节点权限
- a:ADMIN:设置权限
ACL 命令
- getAcl 命令
获取节点的 acl 权限信息
- setAcl 命令
设置节点的 acl 权限信息
- addauth 命令
注册/登录 zk用户用于 acl 的 auth、digest 权限机制,注册时输入明文密码,密码在zk里通过加密存储
acl world 示例
getAcl /test // 获取权限信息
上图说明:world 类型的 scheme 权限机制,用户是 anyone 匿名用户,cdrwa 是所有权限
setAcl /test world:anyone:crwa // 设置权限,重新 getAcl 权限就是 crwa
acl auth/digest 示例
auth 和 digest 区别,auth 是明文的,digest 是加密的
先 addauth 注册用户,不然会报 Acl is not valid 的错误
- 注册一个 zhangsan 的账号,密码是 123456
addauth digest zhangsan:123456
- 给节点 设置 auth 权限,表示只有 zhangsan 才有权操作
setAcl /names/zhangsan auth:zhangsan:123456:cdrwa
- 查看设置后的节点权限,存入zk 服务中的密码是经过BASE64(SHA1(password))加密后的的密码,可以在设置 digest 时直接使用
- 给节点设置 digest 权限,表示只有zhangsan 才有权操作
setAcl /names/test digest:zhangsan:jA/7JI9gsuLp0ZQn5J5dcnDQkHA=:cdrwa
- 当客户端退出重新连接服务端时,操作节点,提示 Insufficient permission 无权操作,表示只有 zhangsan有权操作
- 登录 zhangsan 账号后,可以操作节点了
acl ip 示例
设置节点只有指定的 ip 才有操作权限 // 执行多次会覆盖之前的,需要加ip的话,带上之前的ip
setAcl /names/ip ip:192.168.189.77:cdrwa // 多个ip 使用 英式逗号分隔 示例 ip:192.168.1.1:cdrwa,ip:127.0.0.1:cdrwa
acl super 超级管理员
1:修改 zkServer.sh 脚本,增加 super 管理员
# 超级管理员 账号:张三,密码:123456 是BASE64(SHA1(123456))加密后的密码
"-Dzookeeper.DigestAuthenticationProvider.superDigest=zhangsan:jA/7JI9gsuLp0ZQn5J5dcnDQkHA="
2:重启 zk 服务
./zkServer.sh restart
3:使用 super 超级管理员,操作节点
我们使用一个没有操作权限的节点,提示 Insufficient permission 无权操作
现在我们使用 super 权限用户操作这个节点
登录 super 超级管理员 账号
addauth digest zhangsan:123456 # 超级管理员 用户是 zhangsan 密码是 123456
登录成功后 就可以操作节点了
zookeeper 四字命令
官网文档:ZooKeeper: Because Coordinating Distributed Systems is a Zoo
什么是 四字命令?
ZooKeeper响应一小部分命令。每个命令由四个字母组成。您可以在客户端端口通过telnet或nc向ZooKeeper发出命令。
安装 nc
yum install nc -y
修改 zoo.cfg 配置,然后重启 zk 服务
# 新增
4lw.commands.whitelist=*
四字命令语法
# [commond] : 写四字命令, [ip] : zk 服务ip, [port] : zk 服务端口
echo [commond] | nc [ip] [port]
# 示例
echo stat | nc 192.168.189.77 2181
四字命令如下
stat:列出服务器和连接的客户端的详细信息,mode模式(单机还是集群)
ruok:检测服务器是否在正常运行,如果在运行会返回imok,未运行不会响应
conf:打印有关服务配置的详细信息(包括zoo.cfg 配置)
cons:列出连接到此服务器的所有客户端的完整连接/会话详细信息。包括接收/发送的数据包数量、会话id、操作延迟、最后执行的操作等信息
dump:列出未处理的会话和临时节点
envi:打印有关服务环境的详细信息,环境变量、服务器信息、内存信息
srvr:列出服务器的完整详细信息,和 stat 类似
srst:重置服务器统计信息
crst:重置所有连接的连接/会话统计信息
wchs:列出服务器watch监视的简要信息
wchc:按会话列出服务器watch监视的详细信息。这将输出带有关联监视(路径)的会话(连接)列表。请注意,根据监视的数量,此操作可能很昂贵(即影响服务器性能),请谨慎使用
wchp:按路径列出服务器watch监视的详细信息。这将输出带有关联会话的路径(znode)列表。请注意,根据监视的数量,此操作可能很昂贵(即影响服务器性能),请谨慎使用
dirs:以字节为单位显示快照和日志文件的总大小
mntr:输出可用于监视群集运行状况
isro:检测服务器状态,如果处于只读模式,服务器将以“ro”响应;如果不处于只读模式,则服务器将响应“rw”
hash:返回与zxid关联的树摘要的最新历史记录
zookeeper 集群
zookeeper是按照Paxos算法进行选举的,这个算法也称之为半数选举机制。
所有节点都有投票权,当一个几点票数过半,这个节点就是leader。
zookeeper机制规定,当有新的节点加入时,没有选举出leader时之前票数作废,重新投票。
leader产生后,其他节点投票给leader。1)半数机制:集群中半数以上机器存活,集群可用。所以Zookeeper适合安装奇数台服务器。
2)Zookeeper虽然在配置文件中并没有指定Master和Slave。但是,Zookeeper工作时,是有一个节点为Leader,其他则为Follower,Leader是通过内部的选举机制临时产生的。
搭建伪分布式集群
- 准备 3 份 zookeeper
1.1:编辑 zookeeper01 目录的 zoo.cfg 配置文件
tickTime=2000
initLimit=10
syncLimit=5
clientPort=2181
dataDir=/usr/local/zookeeper01/dataDir
dataLogDir=/usr/local/zookeeper01/dataLogDir
# 指定节点=ip:集群中数据传播端口:其他节点宕掉后选举模式使用的端口
server.1=192.168.189.78:2888:3888
server.2=192.168.189.78:2889:3889
server.3=192.168.189.78:2890:3890
1.2:在 dataDir 目录下,创建 myid 文件,文件内容 写 1
2.1:编辑 zookeeper02 目录的 zoo.cfg 配置文件
tickTime=2000
initLimit=10
syncLimit=5
clientPort=2182
dataDir=/usr/local/zookeeper02/dataDir
dataLogDir=/usr/local/zookeeper02/dataLogDir
server.1=192.168.189.78:2888:3888
server.2=192.168.189.78:2889:3889
server.3=192.168.189.78:2890:3890
2.2:在 dataDir 目录下,创建 myid 文件,文件内容 写 2
3.1:编辑 zookeeper03 目录的 zoo.cfg 配置文件
tickTime=2000
initLimit=10
syncLimit=5
clientPort=2183
dataDir=/usr/local/zookeeper03/dataDir
dataLogDir=/usr/local/zookeeper03/dataLogDir
server.1=192.168.189.78:2888:3888
server.2=192.168.189.78:2889:3889
server.3=192.168.189.78:2890:3890
3.2:在 dataDir 目录下,创建 myid 文件,文件内容 写 3
4:进入各自节点的 bin 目录 使用 ./zkServer.sh start 启动 3 个节点
5:使用 zkCli.sh 客户端连接 zk 服务,创建节点,测试创建的节点是否被其他集群节点同步
./zkCli.sh -server localhost:2181
可以看到上图中,数据都有同步,表示集群搭建成功
搭建真实分布式集群
准备 3 台服务器,ip地址分别是
192.168.189.79
192.168.189.80
192.168.189.81
1:下载zookeeper,下载地址:releases
注意:需要JDK1.8_u211 以上本版
将下载的 zookeeper 安装包上传到 3 台服务器的 /usr/local 目录下,进行tar -zxvf 解压缩
配置环境变量 vim /etc/profile 使环境变量生效 source /etc/profile
export ZOOKEEPER_HOME=/usr/local/zookeeper
export PATH=$PATH:$ZOOKEEPER_HOME/bin:$JAVA_HOME/bin
2:编辑 zookeeper conf目录的 zoo_sample.cfg 配置文件 重命名为 zoo.cfg
三台服务器的 zoo.cfg 都配置成如下内容
Time=2000
initLimit=10
syncLimit=5
clientPort=2181
dataDir=/usr/local/zookeeper/dataDir
dataLogDir=/usr/local/zookeeper/dataLogDir
# server.X 这个X对应着myid的值
server.1=192.168.189.79:2888:3888
server.2=192.168.189.80:2888:3888
server.3=192.168.189.81:2888:3888
3:为 三台服务器分别指定不同的 myid,在 zookeeper/dataDir 目录下新建 myid 文件,文件内容如下
192.168.189.79 的 myid 值是 1
192.168.189.80 的 myid 值是 2
192.168.189.81 的 myid 值是 3
4:分别启动 3 台 zk 服务
./zkServer.sh start
注意:启动时 dataDir 目录 和 dataLogDir 目录中,除了 myid 文件外,一定不要有其他文件,有其他文件就rm -rf 删除,不然启动会报错。注意防火墙要开放 2888、3888 端口
// 如果启动报错,使用 ./zkServer.sh start-foreground 可以打印启动信息,包括报错信息
5:启动完成后,可以使用 ./zkServer.sh status 命令查看集群状态