zookeeper介绍: 自己问度娘吧
zookeeper数据结构:
就是树形结构,每个节点有自己的属性值,记录着这个节点的所有变化, 文件系统差不多
勉强截个图
zookeeper节点类型
1.持久节点** (PERSISTENT)
默认的节点类型。创建节点的客户端与zookeeper断开连接后,该节点依旧存在 。
2.持久节点顺序节点**(PERSISTENT_SEQUENTIAL)
所谓顺序节点,就是在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号
3.临时节点**(EPHEMERAL)
和持久节点相反,当创建节点的客户端与zookeeper断开连接后,临时节点会被删除
4.临时顺序节点**(EPHEMERAL_SEQUENTIAL)
顾名思义,临时顺序节点结合和临时节点和顺序节点的特点:在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号;当创建节点的客户端与zookeeper断开连接后,临时节点会被删除。
zookeeper安装
最新的zookeeper下载地址:
http://mirrors.cnnic.cn/apache/zookeeper/
推荐使用zookeeper-3.4.14/ 里的zookeeper-3.4.14.tar.gz(Windows和Linux都使用这个免安装包)。
解压后,在conf中新建zoo.cfg,或者把zoo_sample.cfg粘贴并重命名。
zoo.cfg文件类容:
# 集群Leader和Follower服务器之间、服务器和客户端之间通信的心跳单元毫秒数
tickTime=2000
# 集群Follower服务器同步Leader服务器时的最大尝试次数
initLimit=10
# 集群Leader服务器检测其他服务器是否存活的最大尝试次数
syncLimit=5
# 服务器对客户端开放的服务端口
clientPort=2181
# 临时文件(快照文件)的存放位置 linux改为对应的路径
dataDir=D:/zookeeper-3.4.14/data
# 日志的存放位置 linux改为对应的路径
dataLogDir=D:/zookeeper-3.4.14/log
linux我一般安装再/usr/local/路径下
zkcli命令
win下面运行的是.cmd结尾的文件,linux下运行的是.sh结尾的文件
我这里以linux命令讲解
启动:
#切换至bin目录
[root@localhost ~]# cd /usr/local/zookeeper-3.4.14/bin
#启动
[root@localhost bin]# ./zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper-3.4.14/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
客户端连接
连接远程服务端:./zkCli.sh -timeout 0 -r -server 192.168.1.101:2181
连接本地服务端:./zkCli.sh #没有参数默认是localhost:2181
[root@localhost bin]# ./zkCli.sh
Welcome to ZooKeeper! #看到这恭喜你连接成功
JLine support is enabled
2019-09-02 03:28:30,871 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@879] - Socket connection established to localhost/0:0:0:0:0:0:0:1:2181, initiating session
2019-09-02 03:28:30,919 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1299] - Session establishment complete on server localhost/0:0:0:0:0:0:0:1:2181, sessionid = 0x100000829f60001, negotiated timeout = 30000
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
查看帮助,即查看又那些命令:
[zk: localhost:2181(CONNECTED) 0] h
ZooKeeper -server host:port cmd args
stat path [watch] #查看节点状态 watch可选, 加上该节点就有监听状态, 当值又所改变的话,就会触发监听,通知该节点又变化
set path data [version] #修改节点数据 version可选 版本 建议带上该字段
ls path [watch] #查询所有节点 例如 ls /hc
delquota [-n|-b] path 删除节点配额
ls2 path [watch] # 包含该节点的详细信息,如子节点总数等
setAcl path acl #设置节点权限
setquota -n|-b val path #列出节点配额 n:表示子节点的最大个数 b:表示数据值的最大长度 val:子节点最大个数或数组值的最大长度 path:节点路径
history
redo cmdno
printwatches on|off
delete path [version] #删除节点 又子节点存在的话需要用递归删除
sync path
listquota path #列出节点配额
rmr path #递归删除
get path [watch] #获取节点信息
create [-s] [-e] path data acl #创建节点 必须指定根目录 -s:可选 顺序节点 -e:可选 临时节点 path路径 data: 数据 acl授权
addauth scheme auth #输入认证授权信息,注册时输入明文密码,但是在zk里,以加密的形式保存
quit
getAcl path #获取节点权限
close #关闭连接
connect host:port #开启连接
setAcl path acl
# 这是其中两种授权方式的列子,其中rwadc分别代表读、写、管理、删除、查询五种方式,可选其中一种或者几种
# 1.auth方式
addauth disgest username:password #(用户名和密码)
setAcl /auth auth:username:password:rwadc
# 2.digest方式
# 先将密码明文加密,即先使用sha1,再使用base64
echo -n test:test | openssl dgst -binary -sha1 | openssl base64
# 将生成的密文设为密码
setAcl /path digest:用户名:密码密文:权限
# 3.访问,两种方式都是这样
addauth digest 用户名:密码明文
get path
实例
#创建
[zk: localhost:2181(CONNECTED) 1] create -s /hello world
Created /hello0000000003
#查看
[zk: localhost:2181(CONNECTED) 3] ls /
[hcclass0000000000, hc, hello0000000003, zookeeper]
#删除
[zk: localhost:2181(CONNECTED) 4] delete /hcclass0000000000
[zk: localhost:2181(CONNECTED) 7] ls /
[hc, hello0000000003, zookeeper]
#获取信息
[zk: localhost:2181(CONNECTED) 8] get /hc
123456 #值
cZxid = 0x16 #节点事务
ctime = Fri Aug 30 15:39:27 EDT 2019 #节点创建时间
mZxid = 0x18 #节点最后一次改变的事务
mtime = Fri Aug 30 15:42:25 EDT 2019 #节点最后一次改变的时间
pZxid = 0x16
cversion = 0
dataVersion = 1 #数据版本
aclVersion = 0 #权限版本
ephemeralOwner = 0x0 #子节点事务,没有子节点该值为0
dataLength = 6 #数据长度
numChildren = 0 #子节点数量
[zk: localhost:2181(CONNECTED) 9]
# 修改值
[zk: localhost:2181(CONNECTED) 9] set /hc hahahaha
cZxid = 0x16
ctime = Fri Aug 30 15:39:27 EDT 2019
mZxid = 0x21
mtime = Mon Sep 02 03:50:03 EDT 2019
pZxid = 0x16
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0
[zk: localhost:2181(CONNECTED) 12] get /hc
hahahaha
zookeeper session
用于客户端与服务端之间的连接,可设置超时时间,通过心跳包的机制(客户端向服务端ping包请求)检查心跳结束,session就过期
session过期的时候,该session创建的所有临时节点都会被抛弃
使用close命令是立即断开连接 会话立即清除
如果使用ctrl + c 强制退出的话会话还不会立即清除,当心跳包去检测的时候发现客户端不存在了,才会断掉
zookeeper watch
对节点的watcher操作 get stat
针对每一个节点的操作,都可以有一个监控者,当节点发生变化,会触发watcher事件 zk中watcher是一次性的,触发后立即销毁 所有有监控者的节点的变更操作都能触发watcher事件
子节点的watcher操作(监控父节点,当父节点对应的子节点发生变更的时候,父节点上的watcher事件会被触发) ls ls2 增删会触发、修改不会,如果子节点再去新增子节点,不会触发(也就是说,触发watcher事件一定是直系子节点)
例如:
zookeeper权限控制
针对节点可以设置相关的读写等权限,目的是为了保证数据的安全性
权限permissions可以指定不同的权限范围及角色
常用的命令
getAcl 获取节点权限
setAcl 设置节点权限
addauth scheme auth 输入认证授权信息,注册时输入明文密码,但是在zk里,以加密的形式保存
[zk: localhost:2181(CONNECTED) 14] getAcl /hc
'world,'anyone
: cdrwa
scheme 授权机制
world下只有一个id,也就是anyone,表示所有人 world:anyone:permissions
auth 代表认证登录,需要注册用户有权限才可以 auth:user:password:permissions
digest 需要密码加密才能访问 digest:username:BASE64(SHA1(password)):permissions(跟auth区别在于,auth明文,digest为密文)
ip ip:localhost:psermissions
super 代表超管,拥有所有的权限;
打开zk目录下的/bin/zkServer.sh服务器脚本文件,找到如下一行:
nohup $JAVA "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}"
加上 "-Dzookeeper.DigestAuthenticationProvider.superDigest=super:xQJmxLMiHGwaqBvst5y6rkB6HQs="
此处后面的密文为密码加密后的
id:允许访问的用户
permissions:权限组合字符串
cdrwa
c create 创建子节点
d delete 删除子节点
r read 读取节点的数据
w write 写入数据
a admin 可管理的权限
cdrwa cdr cdw
注册用户
[zk: localhost:2181(CONNECTED) 15] addauth digest hc:hc
设置节点访问权限
两种方式: 解释命令的时候又说过
- ----------- setAcl /hc digest:hc:hc:cdrda
- ----------- setAcl /hc auth:hc:hc:cdrda
[zk: localhost:2181(CONNECTED) 1] create /test test
Created /test
[zk: localhost:2181(CONNECTED) 4] addauth digest haha:hehe
[zk: localhost:2181(CONNECTED) 5] setAcl /test auth:haha:hehe:cdrwa
#设置成功返回节点信息
cZxid = 0x16
ctime = Fri Aug 30 15:39:27 EDT 2019
mZxid = 0x23
mtime = Mon Sep 02 04:00:24 EDT 2019
pZxid = 0x16
cversion = 0
dataVersion = 3
aclVersion = 1
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0
再次访问test节点
[zk: localhost:2181(CONNECTED) 6] getAcl /test
'digest,'haha:bL0chiGZ71rbQEQEyfbI1sfjuHo=
: cdrwa
从新再开cmd访问
acl的使用场景
开发环境跟测试环境,使用acl就可以进行分离,开发者无权去操作测试的节点
生产环境上控制指定ip的服务可以访问相关的节点
zookeeper集群
zookeeper集群中的三种角色以及其各自的作用
leader:作为整个zk集群写请求的唯一处理者,并负责进行投票的发起和决议,更新系统的状态。
follower:接收客户端请求,处理读请求,并向客户端返回结果;将写请求转给 Leader;在选举 Leader过程中参与投票。
observer:可以理解为无选举投票权的 Flollower,其主要是为了协助 Follower 处理更多的读请求。如果 Zookeeper 集群的读请求负载很高,或者客户端非常非常多,多到跨机房,则可以设置一些 Observer 服务器,以提高读取的吞吐量。
zookeeper集群中常见的三种模式及各种模式出现的时机
zookeeper的核心是广播机制,该机制保证了各个zk之间数据同步(数据一致性)。zk实现的机制为ZAB协议
恢复模式: 如果leader崩溃,这个时候就会进入恢复模式,使整个zk集群恢复到正常的工作状态
同步模式:新的leader选举出来后,就乎进入同步模式(各个follower会去同步新的leader上的数据),当大多数zkServer完成了与leader的状态同步之后,恢复模式就结束,同步模式贯穿在恢复模式中
广播模式:客户端想写入数据,这个时候leader发起提议,当leader的提议被大多数的zkServer统一之后,leader就会去修改自身的数据,并将修改后的数据广播给其他的follower
zk集群选举核心概念及选举时状态
myid
这是 zk 集群中服务器的唯一标识,称为 myid。例如,有三个 zk 服务器,那么编号分别是 1,2,3。
zxid
--------------------epoch ----------------------------------------------------- xid--------------------
00000000000000000000000000000000–00000000000000000000000000000000
zxid 为 Long 类型,其中高 32 位表示 epoch,低 32 位表示 xid。即 zxid 由两部分构成:epoch 与 xid。
每个 Leader 都会具有一个不同的 epoch 值,表示一个时期、时代。新的 Leader 产生,则会更新所有 zkServer 的 zxid 中的 epoch。 而 xid 则为 zk 的事务 id,每一个写操作都是一个事务,都会有一个 xid。每一个写操作都需要由 Leader 发起一个提议,由所有 Follower 表决是否同意本次写操作。
逻辑时钟
逻辑时钟,Logicalclock,是一个整型数,该概念在选举时称为 logicalclock,而在 zxid 中则为 epoch 的值。即 epoch 与 logicalclock 是同一个值,在不同情况下的不同名称。
zk的选举状态
LOOKING,选举状态(查找 Leader 的状态)。
LEADING,领导者状态。处于该状态的服务器称为 Leader。
FOLLOWING,随从状态,同步 leader 状态。处于该状态的服务器称为 Follower。
OBSERVING,观察状态,同步 leader 状态。处于该状态的服务器称为 Observer。
zk集群选举发生的时机及选举算法
发生时机:整个集群群龙无首的时候(1.服务启动 2.leader宕机之后)
选举机制:集群中,半数zkServer同意,则产生新的leader(搭建集群时,一般都是奇数个)
三台服务器,最多允许一台宕机,四台服务器,也是最多允许一台宕机
选举算法:
对比(myid,zxid),先对比zxid,zxid大者(大表示数据越新)胜出,成为leader,如果zxid一致,则myid大者成为leader
实战zookeeper集群
解压zookeeper压缩包
修改conf文件夹下的配置文件zoo_sample.cfn文件内容如下,并重命名为zoo.cfn
最好去掉这些中文注释
# 集群Leader和Follower服务器之间、服务器和客户端之间通信的心跳单元毫秒数
tickTime=2000
# 集群Follower服务器同步Leader服务器时的最大尝试次数
initLimit=10
# 集群Leader服务器检测其他服务器是否存活的最大尝试次数
syncLimit=5
# 服务器对客户端开放的服务端口
clientPort=2181
# 临时文件(快照文件)的存放位置
dataDir=/usr/local/zookeeper-3.4.14/data
# 日志的存放位置
dataLogDir=/usr/local/zookeeper-3.4.14/log
#centos123是在虚拟机hosts中配置的别名,2888是各个zk服务之间的通讯端口,3888是leard选举端口 server.1的1是myid文件中的唯一id
server.1=centos101:2888:3888
server.2=centos102:2888:3888
server.3=centos103:2888:3888
在解压包下新建data目录
创建文件myid
然后将解压的文件传输到各个虚拟机得usr/local/下
将data目录下得myid文件中得1,修改成对应得2, 3
然后依次启动3台虚拟机
这里我是以root用户启动的, 因为zookeeper没有像elaticsearch一样强制不能以root权限启动,所以我就没有新建用户, 不过一般建议不要用root用户来启动
新建用户
useradd zookeeper
三台服务器的zk的权限,都赋给zookeeper用户
chown -R zookeeper:zookeeper zookeeper-3.4.12/
我这里就不新增用户了
关闭防火墙
systemctl stop firewalld.service
进入zk的bin目录 给到操作权限 运行启动命令
chmod +x *.sh
./zkServer.sh start
如下图
三台机子均启动完成之后,可以使用./zkServer.sh status去查看状态
启动没报错,但是查看状态去报没有启动的错误,这时候就要去看日志了:
bin目录下的zookeeper.out
cat zookeeper.out
例如配置文件不对报如下异常:
若没有任何异常则 最终效果:
从
从
主
测试主节点宕机了
关闭主节点 103
查看101和102的zookeeper的状态
我这里102就变成了leader了
至此集群加测试就完成了
最后提供一个zookeeper可视化工具ZooInspector,
下载地址
https://issues.apache.org/jira/secure/attachment/12436620/ZooInspector.zip
解压到你喜欢的目录
找到build目录下的zookeeper-dev-ZooInspector.jar包
在该目录下运行
java -jar zookeeper-dev-ZooInspector.jar
界面如下: