1、概念
- Zookeeper是一个Apache Hadoop项目下的一个开源分布式管理服务,通过树形目录服务+事件监听通知去管理分布式环境下的数据和同步分布式集群数据
- 特点:cp架构、顺序一致性、观察者模式实现监听机制、事务持久化、分布式
- Zookeeper常见的应用场景有服务注册、服务配置、分布式锁等
2、Zookeeper数据模型
- Zookeeper是一个树形目录服务,数据模型和Unix的文件系统类似。
- 每一个节点被称为Znode,每一个节点上都会保存自己的数据和节点信息。
- 节点可以拥有子节点,同时也允许少量数据存储在该节点中 (默认上限1MB,配置可改)
- 节点分为四大类:
- PERSISTENT持久化节点
- EPHEMERAL临时化节点:-e
- PERSISTENT_SEQUENTIAL持久化顺序节点:-s
- EPHEMERAL_SEQUENTIAL临时化顺序节点:-es
- 容器节点(Container),3.5.3新增的特性,没有子节点的容器节点会被清除掉:-c
- TTL节点,3.5.3新增的特性,位节点设定了失效时间:-t time /node
3、安装和常用命令
1、安装条件
想要安装zookeeper,必须先在linux中安装好jdk。安装步骤见:
2、下载并解压zookeeper压缩包
1. 先进入/usr/local/目录,也可以是其他的目录:
[root@localhost /]# cd /usr/local
2. zookeeper安装包可以在官网下载。
也可以在后面这个地址下载 http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz
如果链接打不开,就先打开 http://mirror.bit.edu.cn/apache/zookeeper , 再选择版本。
在此目录下载zookeeper安装包:
[root@localhost local]# wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz
3. 解压:
[root@localhost local]# tar -zxvf zookeeper-3.4.13.tar.gz
3、编辑配置文件
1.进入conf目录:
[root@localhost local]# cd zookeeper-3.4.13/conf
2. 将zoo_sample.cfg这个文件复制为zoo.cfg (必须是这个文件名)
[root@localhost conf]# cp zoo_sample.cfg zoo.cfg
3. zoo.cfg文件参数
# 心跳时长,ms 固定时长发送心跳
tickTime=2000
# 连接时长,leader和follower连接时允许的最大心跳次数所耗时长
initLimit=10
# 保活时长,leader和follower同步数据时允许的最大心跳次数所耗时长
syncLimit=5
# 数据保存地址
dataDir=/usr/local/zookeeper-cluster/zookeeper-1/data
# 日志保存路径,不配置默认放在dataDir下
dataLogDir=/usr/local/zookeeper-cluster/zookeeper-1/log
# 为客户端通信开放的服务端口
clientPort=2181
4. 按 i 进入编辑模式,修改以下内容:
dataDir=/tmp/zookeeper/data
dataLogDir=/tmp/zookeeper/log
5. 在tmp目录创建目录。
[root@localhost conf]# mkdir /tmp/zookeeper
[root@localhost conf]# mkdir /tmp/zookeeper/data
[root@localhost conf]# mkdir /tmp/zookeeper/log
6.如果是配置集群,还需要在前面配置过的dataDir路径下新增myid文件
[root@localhost conf]# cd /tmp/zookeeper/data
[root@localhost data]# touch myid
[root@localhost data]# vim myid
在data目录下创建文件,文件名为“myid”, 编辑该“myid”文件,并在对应的IP的机器上输入对应的编号。
如在192.168.180.132上,“myid”文件内容就是1。在192.168.180.133上,内容就是2。
4、配置环境变量
1.上面的操作都完事之后,我们需要配置一下环境变量,配置环境变量的命令如下:
[root@localhost zookeeper-3.4.13]# export ZOOKEEPER_INSTALL=/usr/local/zookeeper-3.4.13/
[root@localhost zookeeper-3.4.13]# export PATH=$PATH:$ZOOKEEPER_INSTALL/bin
5、启动zookeeper
1.进入bin目录,并启动zookeep。如果不是在bin目录下执行,启动zookeeper时会报错: bash: ./zkServer.sh: No such file or directory
注意: ./zkServer.sh start前面的 . 不可忽略。
[root@localhost local]# cd /usr/local/zookeeper-3.4.13/bin
[root@localhost bin]# ./zkServer.sh start
2.启动成功效果如下:
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper-3.4.13/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
3.zookeeper的服务端启动后,还需要启动zookeeper的客户端:
[root@localhost bin]# ./zkCli.sh
如果是连接多个不同的主机节点,可以使用如下命令:
./zkCli.sh -server 192.168.180.132:2888
启动成功效果如下:
Connecting to localhost:2181
..........
..........
..........
Welcome to ZooKeeper!
2018-10-25 21:04:54,407 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1029] - Opening socket connection to server localhost/0:0:0:0:0:0:0:1:2181. Will not attempt to authenticate using SASL (unknown error)
JLine support is enabled
2018-10-25 21:04:54,471 [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
[zk: localhost:2181(CONNECTING) 0] 2018-10-25 21:04:54,501 [myid:] - INFO [main-SendThread(localhost:2181):ClientCnxn$SendThread@1303] - Session establishment complete on server localhost/0:0:0:0:0:0:0:1:2181, sessionid = 0x10000712e6f0000, negotiated timeout = 30000
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
4.查看状态:
[root@localhost bin]# ./zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper-3.4.13/bin/../conf/zoo.cfg
Mode: standalone
6、集群搭建
这里搭一个伪集群(正式集群也是一样步骤)。zookeeper-1、zookeeper-2和zookeeper-3三个目录下都放置zookeeper服务
每个zookeeper-x目录下的zookeeper服务都按照前面五步去执行,但是有几点要改变下:
- 由于同一台机器,环境变量没必要配置了,发挥不了作用;
- 在每个zookeeper-x目录下单独创建data目录、log目录,每个服务的zoo.cfg的dataDir使用各自的data目录、log目录。如图:
- 由于同一台机器,每个服务的zoo.cfg的clientPort不能相同;
在每个服务的zoo.cfg中都配置下面内容,集群配置就这一步完成了
# server.服务id(myid)=ip:服务间的通信端口:服务间投票端口
server.1=192.168.180.132:2888:3888
server.2=192.168.180.133:2888:3888
server.3=192.168.180.134:2888:3888
搭建完成后,去各自的bin目录启动服务:./zkServer.sh start
全部启动完成后,可以看到打印日志有展示服务是主还是备:如下,Mode:follower即备机,如果Mode: leader则为主机
[root@rocketmq-nameserver1 conf]# cd /usr/local/zookeeper-cluster/zookeeper-3/apache-zookeeper-3.6.0-bin/bin/
[root@rocketmq-nameserver1 bin]# ./zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /usr/local/zookeeper-cluster/zookeeper-3/apache-zookeeper-3.6.0-bin/bin/../conf/zoo.cfg
Client port found: 2183. Client address: localhost.
Mode: follower
7、脚本
#!/bin/bash
#1、在一台机器模拟集群,远程ip均是本机,ssh远程登录需要配置免密,不然脚本执行过程中会提示输入密
#码,影响效率
#2、shell命令执行时可能会出现环境配置问题,因为shell从/etc/bashrc读取环境变量,所以需要把相关变#量从profile复制过来,比如Java变量 配置方式都一样
case $1 in
"start"){
for i in 1 2 3
do
echo ------------- zookeeper $i start successful
ssh localhost "/usr/local/zookeeper-cluster/zookeeper-$i/apache-zookeeper-3.6.0-bin/bin/zkServer.sh start"
done
}
;;
"stop"){
for i in 1 2 3
do
echo ------------- zookeeper $i stop
ssh localhost "/usr/local/zookeeper-cluster/zookeeper-$i/apache-zookeeper-3.6.0-bin/bin/zkServer.sh stop"
done
}
;;
"status"){
for i in 1 2 3
do
echo ------------- zookeeper $i status:
ssh localhost "/usr/local/zookeeper-cluster/zookeeper-$i/apache-zookeeper-3.6.0-bin/bin/zkServer.sh status"
done
}
;;
esac
【注:】
- 在一台机器模拟集群,远程ip均是本机,ssh远程登录需要配置免密,不然脚本执行过程中会提示输入密码,影响效率,没有 ssh 安装后配置 keygen 即可
- shell命令执行时可能会出现环境配置问题,因为shell从/etc/bashrc读取环境变量,所以需要把相关变#量从profile复制过来,比如Java变量 配置方式都一样
8、三种编号
- SID:服务器ID。用来标识机器,用myid表示,不可冲突;
- ZXID:zk的 curd 用了锁保证了同步,ZXID是一个基于此的事务ID集合,用来标识一次服务器状态的变更,具体由节点的cZxid、mZxid、pZxid三个参数构成;
- Epoch:长度32位,每个Leader任期的代号。选举状态下新Leader会递增一次Epoch,然后同步到Follower
9、选举机制(面试重点)
如上图有5台zookeeper机器,简称zk集群:
1、首次启动集群
逻辑如下
- zk1启动发动一次投票,投自己一票。此时zk1获得1票但不够半数以上(3票),zk1保持状态为LOOKING;
- zk2启动发动一次投票,投自己一票。此时zk1依然投自己一票,zk1、zk2各一票保持状态为LOOKING;
- zk3启动发动一次投票,投自己一票。此时zk1、zk2投zk3一票,zk1、zk2各0票,zk3获得3票,达到半数以上(3票),zk3成为leader。此时zk1、zk2改变状态为FOLLOWING,zk3状态为LEADING;
- zk4启动发动一次投票,投自己一票。此时zk1、zk2、zk3均不是LOOKING状态,信息不变。zk4状态为FOLLOWING;
- zk5同zk4
逻辑图如下
2、宕机集群恢复
当前集群可能处于两种情况:
- 集群中本来就已经存在一个Leader:对于第一种已经存在Leader的情况,机器试图去选举Leader时,会被告知当前服务器的Leader信息,对于该机器来说,仅仅需要和Leader机器建立连接,并进行状态同步即可
- 集群中确实不存在Leader:假设zk集群中SID分别为1、2、3、4、5,ZXID分别为8、8、8、7、7。某一时刻,zk3(Leader)、zk5宕机,触发Leader选举
- 存活的zk1、zk2、zk4开始选举:
- 确定各机器的 (EPOCH,ZXID,SID)
- zk1:(1,8,1),zk2:(1,8,2),zk4:(1,7,4)
- 首先判断EPOCH,大的胜出;
- EPOCH判断一样大,则执行ZXID判断:8、8、7,大的胜出;
- ZXID判断后最大有两个:zk1和zk2,则执行SID判断:1、2,大的胜出
- SID判断后zk2最大,zk2当选
- 新leader将递增epoch作为新的epoch并同步到各个follower
- 存活的zk1、zk2、zk4开始选举:
3、数据同步
原leader发送proposal申请时,接受到的follower会磁盘存储proposal,因此新leader可以收集follower的事务日志和snapshot存储的zxid定位到待提交的proposal(很可能不止一条),然后提交到从机同步数据(follower和oberserver)
4、工作状态
在选举状态下完成集群恢复和数据恢复(集群全部停止客户端工作),然后才是切换到工作状态,即开启客户端通信和zab协议
10、遇到问题怎么解决?
zookeeper的出错日志会记录在 zookeeper.out。
当前处于哪个目录,执行完zkServer.sh start命令, zookeeper.out就会写在哪个目录。
vim zookeeper.out 可以查看报错信息。然后再搜索解决。
11、zookeeper客户端命令
通过 ./zkCli.sh 进入客户端后,就可以使用命令来操作zookeeper了。
【注:】zookeeper的节点是并发管理,也就是加锁做了同步,好文推荐:zk并发
1.监听节点
使用 addWatch 命令,可以监听节点的变动并提示
- addWatch [-m mode] path
- 其中 mode 是指 [PERSISTENT, PERSISTENT_RECURSIVE] 默认 PERSISTENT_RECURSIVE
- PERSISTENT表示仅监听本节点,PERSISTENT_RECURSIVE表示监听本节点及子节点,更耗系统资源
客户端1 监听 节点t,此时未创建 节点t,但不影响监听
[zk: localhost:2181(CONNECTED) 16] addWatch /t
[zk: localhost:2181(CONNECTED) 17] ls /
[]
此时 客户端1 收到提示,说明其它客户端创建了 节点t
[zk: localhost:2181(CONNECTED) 18]
WATCHER::
WatchedEvent state:SyncConnected type:NodeCreated path:/t
WATCHER::
WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/t
客户端1 查询根节点,发现确实 t节点 被创建了
[zk: localhost:2181(CONNECTED) 18] ls /
[t]
2.创建节点
使用 create 命令,可以创建一个zookeeper节点。
create [-s] [-e] path data acl
其中-s表示顺序节点,-e表示临时节点。默认情况下,创建的是持久节点。
path是节点路径,data是节点数据,acl是用来进行权限控制的。
如下:
创建一个叫做/zk-test的节点,内容是"123"
[zk: localhost:2181(CONNECTED) 0] create /zk-test 123
Created /zk-test
创建/zk-test的子节点book,内容是"233"
[zk: localhost:2181(CONNECTED) 7] create /zk-test/book 233
Created /zk-test/book
3.查看节点内容
获取zookeeper指定节点的内容和属性信息。如下:
[zk: localhost:2181(CONNECTED) 1] get -s /zk-test
123
cZxid = 0x3a
ctime = Sun Nov 11 21:50:44 CST 2018
mZxid = 0x3a
mtime = Sun Nov 11 21:50:44 CST 2018
pZxid = 0x3a
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
# 注释
# cZxid 创建节点时的事务ID
# ctime 创建节点时的时间
# mZxid 最后修改节点时的事务ID
# mZxid 最后修改节点时的事务ID
# pZxid 该节点的 子节点列表 最后一次修改的事务ID,添加、删除子节点就会影响子节点列表,而修改子
# 节点的数据内容则不影响(注意,只有子节点列表变更了才会变更pzxid,子节点内容变更不会影响
# pzxid)
# cversion 子节点版本号,子节点每次修改版本号加1
# dataVersion 数据版本号,数据每次修改该版本号加1
# aclVersion 权限版本号,权限每次修改该版本号加1
# ephemeralOwner 创建该临时节点的会话的sessionID。(如果该节点是持久节点,那么这个属性值为0)
# dataLength 该节点的数据长度
# numChildren 直接子节点的数量
4.查看子节点
使用ls命令可以查看指定节点下的所有子节点
以下查看根目录下的所有子节点:
[zk: localhost:2181(CONNECTED) 2] ls /
[zk-test, zookeeper]
查看zk-test节点的子节点:
[zk: localhost:2181(CONNECTED) 3] ls /zk-test
[book]
5.更新节点内容
使用set命令,更新节点内容。格式为:
set path data
其中的data就是要更新的新内容。
[zk: localhost:2181(CONNECTED) 4] set /zk-test 456
cZxid = 0x3a
ctime = Sun Nov 11 21:50:44 CST 2018
mZxid = 0x3b
mtime = Sun Nov 11 22:05:20 CST 2018
pZxid = 0x3a
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
在输出的信息中,可以发现,dataVersion的值由原来的0 变成了 1,这是因为刚才的更新操作导致该节点的数据版本也发生变更。
6.权限设置
设置digest,格式:addauth digest username:password
-
[zk: localhost:2181(CONNECTED) 44] create /t4 44 Created /t4 [zk: localhost:2181(CONNECTED) 45] addauth digest qlq:111222 #增加授权用户,明文用户名和密码 [zk: localhost:2181(CONNECTED) 46] setAcl /t4 auth:qlq:cdwra #授予权限 cZxid = 0x40000001d ctime = Tue Mar 12 15:16:56 CST 2019 mZxid = 0x40000001d mtime = Tue Mar 12 15:16:56 CST 2019 pZxid = 0x40000001d cversion = 0 dataVersion = 0 aclVersion = 1 ephemeralOwner = 0x0 dataLength = 2 numChildren = 0 [zk: localhost:2181(CONNECTED) 48] getAcl /t4 'digest,'qlq:JWNEexxIoeVompjU7O5pZzTU+VQ= : cdrwa
重新连接之后获取会报没权限,需要添加授权用户:
addauth digest usrname:password
,getAcl /zkee -
zk: localhost:2181(CONNECTED) 4] get /t4 Authentication is not valid : /t4 [zk: localhost:2181(CONNECTED) 6] addauth digest qlq:111222 [zk: localhost:2181(CONNECTED) 7] get /t4 44 cZxid = 0x40000001d ctime = Tue Mar 12 15:16:56 CST 2019 mZxid = 0x40000001d mtime = Tue Mar 12 15:16:56 CST 2019 pZxid = 0x40000001d cversion = 0 dataVersion = 0 aclVersion = 1 ephemeralOwner = 0x0 dataLength = 2 numChildren = 0
-
- 设置白名单,格式:setAcl 路径 ip:xxx.xxx.xxx.xx1:cdrwa,ip:xxx.xxx.xxx.xx2:cdrwa
- 例如:
setAcl /zkee world:anyone:cdrwa
,getAcl /zkee
- 例如:
-
设置公共权限,即都能访问,也是默认权限,格式:setAcl 路径 world:anyone:cdrwa
例如:setAcl /zkee world:anyone:cdrwa
,getAcl /zkee
7.删除节点
1、delete 命令删除节点,如下
[zk: localhost:2181(CONNECTED) 11] delete /zk-test
Node not empty: /zk-test
存在子节点时,无法删除该节点,需要先删除子节点/zk-test/book,如下
[zk: localhost:2181(CONNECTED) 12] delete /zk-test/book
WATCHER::
WatchedEvent state:SyncConnected type:NodeDeleted path:/zk-test/book
继续尝试删除节点 /zk-test,如下
[zk: localhost:2181(CONNECTED) 13] ls /zk-test
[]
[zk: localhost:2181(CONNECTED) 14] delete /zk-test
[zk: localhost:2181(CONNECTED) 15] ls /
[]
删除成功。
2、deleteall 命令强制删除节点,就算有子节点也不怕
8.状态检查
stat [-w] path
-w 为 监听
[zk: localhost:2181(CONNECTED) 18] stat -w /test
cZxid = 0x130000000a
ctime = Fri Mar 18 19:34:15 CST 2022
mZxid = 0x130000000a
mtime = Fri Mar 18 19:34:15 CST 2022
pZxid = 0x130000000b
cversion = 1
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 0
numChildren = 1
9.帮助命令
执行 help 命令展示所有命令,如下
12、Zookeeper四字命令
1、大多是查询命令,用来获取 ZooKeeper 服务的当前状态及相关信息。
2、不需进入zk客户端,linux终端执行即可。用户在客户端可以通过 nc 向 ZooKeeper 提交相应的命令(如果客户端没有 nc yum安装即可)
3、主要命令(好文推荐:菜鸟教程-四字命令,命令不在白名单解决方法)
- stat:echo stat | nc 127.0.0.1 2181 来查看哪个节点被选择作为follower或者leader
- ruok:echo ruok | nc 127.0.0.1 2181 测试是否启动了该Server,若回复imok表示已经启动。
- dump:echo dump | nc 127.0.0.1 2181 列出未经处理的会话和临时节点。
- kill:echo kill | nc 127.0.0.1 2181 关掉server
- conf:echo conf | nc 127.0.0.1 2181 输出相关服务配置的详细信息。
- cons:echo cons | nc 127.0.0.1 2181 所有连接服务器的客户端的完全连接/会话的详细信息。
- envi:echo envi |nc 127.0.0.1 2181 输出关于服务环境的详细信息(区别于 conf 命令)
- reqs:echo reqs | nc 127.0.0.1 2181 列出未经处理的请求。
- wchs:echo wchs | nc 127.0.0.1 2181 列出服务器 watch 的详细信息。
- wchc:echo wchc | nc 127.0.0.1 2181 通过 session 列出服务器 watch 的详细信息,它的输出是一个与 watch 相关的会话的列表。
- wchp:echo wchp | nc 127.0.0.1 2181 通过路径列出服务器 watch 的详细信息。它输出一个与 session 相关的路径。
13、ZooKeeper服务命令
- 启动ZK服务: sh bin/zkServer.sh start
- 查看ZK服务状态: sh bin/zkServer.sh status
- 停止ZK服务: sh bin/zkServer.sh stop
- 重启ZK服务: sh bin/zkServer.sh restart
4、顺序一致性
zk集群采用一主多从架构,这表示写操作只有一个服务能执行,写操作要关联一个全局事务(zxid),zxid有epoch、事务计数器组成,事务计数器单调递增。zxid的高32位是epoch;低32位是计数器,所以同一任期内,zxid是连续的,每个结点又都保存着自身最新生效的zxid,通过对比新提案的zxid与自身最新zxid是否相差“1”来保证事务严格按照顺序生效的。Leader为了保证提案按ZXID顺序生效,使用了一个ConcurrentHashMap,记录所有未提交的提案,命名为outstandingProposals,key为ZXID,Value为提案的信息。outstandingProposals的逻辑如下:
1、每发起一个提案,会将提案的ZXID和内容放到outstandingProposals中,作为待提交的提案;
2、收到Follower的ACK信息后,根据ACK中的ZXID从outstandingProposals中找到对应的提案,对ACK计数;
3、执行tryToCommit尝试将提案提交,判断流程如下:
3.1:判断当前ZXID之前是否还有未提交提案,如果有,当前提案暂时不能提交;
3.2:判断提案是否收到半数以上ACK,如果达到半数则可以提交;
3.3:如果可以提交,将当前ZXID从outstandingProposals中清除并向Followers广 播提交当前提案;
4、ZookeeperJavaAPI
maven引入
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.7</version>
</dependency>
5、Zookeeper客户端向服务端写请求原理
连接Leader
连接Follower
6、Java客户端API
引入maven
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.7</version>
</dependency>
<!-- Zookeeper的Java类库 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>4.3.0</version>
</dependency>
单元测试,简单举例了创建,判断存在,获取子节点的方法
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
public class zkClient {
// 注意:逗号左右不能有空格
private String connectString = "192.168.48.128:2181,192.168.48.128:2182,192.168.48.128:2183";
private int sessionTimeout = 200000;
private ZooKeeper zkClient;
@Before
public void init() throws IOException {
zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("-------------------------------");
List<String> children = null;
try {
children = zkClient.getChildren("/atguigu", true);
for (String child : children) {
System.out.println(child);
}
System.out.println("-------------------------------");
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
@Test
public void create() throws KeeperException, InterruptedException {
String nodeCreated = zkClient.create("/atguigu/3", "ss2.avi".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
@Test
public void getChildren() throws KeeperException, InterruptedException {
List<String> children = zkClient.getChildren("/", true);
for (String child : children) {
System.out.println(child);
}
// 延时
Thread.sleep(Long.MAX_VALUE);
}
@Test
public void exist() throws KeeperException, InterruptedException {
Stat stat = zkClient.exists("/atguigu", false);
System.out.println(stat==null? "not exist " : "exist");
}
}
7、其它
企业应用
选举机制
超过半数即通过
1、首次选举规则:
- 投票过半数,服务器票数大的胜出
2、Leader宕机重选规则:
- EPOCH大的直接胜出
- EPOCH相同,事物id大的胜出
- 事物id相同,服务器id大的胜出
多少机器组成zk集群合适
- 10台:3台zk
- 20台:5台zk
- 100以上:11台zk
常用命令
ls、get、create、delete ...
服务注册
服务配置
分布式锁
源码
todo
参考资料 :
《从Paxos到zookeeper分布式一致性原理与实践》