Zookeeper

1、概念

  1. Zookeeper是一个Apache Hadoop项目下的一个开源分布式管理服务,通过树形目录服务+事件监听通知去管理分布式环境下的数据和同步分布式集群数据
  2. 特点:cp架构、顺序一致性、观察者模式实现监听机制、事务持久化、分布式
  3. Zookeeper常见的应用场景有服务注册、服务配置、分布式锁等

2、Zookeeper数据模型

  1. Zookeeper是一个树形目录服务,数据模型和Unix的文件系统类似。
  2. 每一个节点被称为Znode,每一个节点上都会保存自己的数据和节点信息。
  3. 节点可以拥有子节点,同时也允许少量数据存储在该节点中 (默认上限1MB,配置可改)
  4. 节点分为四大类:
    1. PERSISTENT持久化节点
    2. EPHEMERAL临时化节点:-e
    3. PERSISTENT_SEQUENTIAL持久化顺序节点:-s
    4. EPHEMERAL_SEQUENTIAL临时化顺序节点:-es
    5. 容器节点(Container),3.5.3新增的特性,没有子节点的容器节点会被清除掉:-c
    6. TTL节点,3.5.3新增的特性,位节点设定了失效时间:-t time /node

3、安装和常用命令

1、安装条件

想要安装zookeeper,必须先在linux中安装好jdk。安装步骤见:

linux安装jdk - 乐之者v - 博客园

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服务都按照前面五步去执行,但是有几点要改变下:

  1. 由于同一台机器,环境变量没必要配置了,发挥不了作用;
  2. 在每个zookeeper-x目录下单独创建data目录、log目录,每个服务的zoo.cfg的dataDir使用各自的data目录、log目录。如图:
  3. 由于同一台机器,每个服务的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

【注:】

  1. 在一台机器模拟集群,远程ip均是本机,ssh远程登录需要配置免密,不然脚本执行过程中会提示输入密码,影响效率,没有 ssh 安装后配置 keygen 即可
  2. shell命令执行时可能会出现环境配置问题,因为shell从/etc/bashrc读取环境变量,所以需要把相关变#量从profile复制过来,比如Java变量 配置方式都一样

8、三种编号

  1. SID:服务器ID。用来标识机器,用myid表示,不可冲突;
  2. ZXID:zk的 curd 用了锁保证了同步,ZXID是一个基于此的事务ID集合,用来标识一次服务器状态的变更,具体由节点的cZxid、mZxid、pZxid三个参数构成;
  3. 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

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服务命令

  1. 启动ZK服务:       sh bin/zkServer.sh start
  2. 查看ZK服务状态: sh bin/zkServer.sh status
  3. 停止ZK服务:       sh bin/zkServer.sh stop
  4. 重启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、首次选举规则:

  1. 投票过半数,服务器票数大的胜出

2、Leader宕机重选规则:

  1. EPOCH大的直接胜出
  2. EPOCH相同,事物id大的胜出
  3. 事物id相同,服务器id大的胜出

多少机器组成zk集群合适

  • 10台:3台zk
  • 20台:5台zk
  • 100以上:11台zk

常用命令

ls、get、create、delete ...

服务注册

服务配置

分布式锁

源码

todo

参考资料 :

《从Paxos到zookeeper分布式一致性原理与实践》

Linux环境下安装Zookeeper_努力改变人生!-CSDN博客_linux 装zookeeper

ZooKeeper集群环境安装与配置_无界编程-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值