资料
Zookeeper入门看这篇就够了
ZooKeeper下载安装(Windows版本)
Zookeeper是什么
是一个分布式服务框架
,是Apache Hadoop 的一个子项目
,它主要是用来解决分布式应用中经常遇到的一些数据管理问题
,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等
。
上面的解释有点抽象,简单来说zookeeper=文件系统+监听通知机制
。
文件系统
Zookeeper维护一个类似文件系统的数据结构
:
每个子目录
项如 NameService 都被称作为 znode(目录节点)
,和文件系统一样,我们能够自由的增加、删除znode
,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的
。
有四种类型的znode:
1 PERSISTENT
-持久化
目录节点
客户端与zookeeper断开连接后,该节点依旧存在
2 PERSISTENT_SEQUENTIAL
-持久化顺序
编号目录节点
客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号
3 EPHEMERAL
-临时目录
节点
客户端与zookeeper断开连接后,该节点被删除
4 EPHEMERAL_SEQUENTIAL
-临时顺序
编号目录节点
客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号
监听通知机制
客户端注册监听它关心的目录节点
,当目录节点发生变化
(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端
。
组成部分
znode
兼具文件和目录两种身份
,既能像文件一样维护着数据、元信息、ACL、时间戳等数据
,又可以像目录已经作为路径的标识的一部分
节点的数据:节点path,以及对应的节点数据
节点的子节点 children
节点的状态 state:用来描述当前节点的创建、修改记录、包括cZxid、ctime等
cZxid:数据节点创建时的事务id
ctime:数据节点创建时的时间
mZxid:数据节点最后一次更新时的事务id
mtime:数据节点最后一次更新时的时间
pZxid:数据节点的子节点最后一次修改时的事务id
cversion:子节点的更改次数
dataVersion:当前节点数据修改次数
aclVersion:节点的ACL修改次数(当前节点对应的权限列表修改次数)
ephemeralOwner:如果当前节点是临时节点,则表示创建该节点会话的SessionID,如果当前节点是持久节点,则该属性为0。
dataLength:数据内容的长度(字节为单位)
numChildren:数据节点当前的子节点个数
节点类型
zookeeper
有两种节点类型
,节点类型在创建的时候即被确定,并且不能修改。
临时节点(Znode):该节点的 生命周期 依赖于创建他们的会话,一旦 session 结束,临时节点将会被清除
虽然每个 Znode 都会绑定到一个客户端 session,但他们对所有客户端还是可见的
需要注意的是临时节点不允许有自己的子节点
持久化节点:此类型的节点声明周期 不依赖于会话 ,并且有在客户端显示的执行删除操作的时候,他们才能被清除
Zookeeper能做什么
zookeeper功能非常强大,可以实现诸如分布式应用配置管理、统一命名服务、状态同步服务、集群管理
等功能,我们这里拿比较简单的分布式应用配置管理为例来说明。
假设我们的程序是分布式部署在多台机器
上,如果我们要改变程序的配置文件,需要逐台机器去修改,非常麻烦
现在把这些配置全部放到zookeeper上
去,保存在 zookeeper 的某个目录节点中
,然后所有相关应用程序对这个目录节点进行监听
,一旦配置信息发生变化
,每个应用程序就会收到 zookeeper 的通知
,然后从 zookeeper 获取新的配置信息应用到系统
中。
Zookeeper单机模式安装
Step1:配置JAVA环境,检验环境:java -version
Step2:下载并解压zookeeper
cd /usr/local
wget http://mirror.bit.edu.cn/apache/zookeeper/stable/zookeeper-3.4.12.tar.gz
tar -zxvf zookeeper-3.4.12.tar.gz
cd zookeeper-3.4.12
Step3:重命名配置文件zoo_sample.cfg
cp conf/zoo_sample.cfg conf/zoo.cfg
Step4:启动zookeeper
bin/zkServer.sh start
Step5:检测是否成功启动,用zookeeper客户端连接下服务端
bin/zkCli.sh
Zookeeper客户端使用
bin/zkCli.sh
运行zookeeper客户端
查看节点列表
ls 命令来查看当前 ZooKeeper 中所包含的内容
ls [-s] [-w] [-R] path
[zk: localhost:2181(CONNECTED) 12] ls /
[default, zookeeper]
查询某个节点下的子节点,但是不会返回孙子节点
-s
参数返回子节点
的信息(旧版本使用ls2命令)
-R
参数返回当前节点以及其下所有节点的列表
,包括当前节点本身
get 节点
查看节点信息
get [-s] [-w] path
-s:节点的详细信息
-w:添加监听器,在当前节点发生变化后,会向当前会话对应的客户端发出通知。
查看节点状态
stat [-w] path
stat只返回节点的信息,不返回节点的数据
create 节点
创建一个新的 znode 节点,使用 create /zkPro myData
zookeeper
的节点分为,有序的持久化节点
、无序的持久化节点
、有序的临时节点
、无序的临时节点
create [-s] [-e] [-c] [-t ttl] path [data] [acl]
-s:有序节点
-e:临时节点
create -s -e /tt "tt" 创建临时有序节点
[zk: localhost:2181(CONNECTED) 13] create /zkPro myData
Created /zkPro
[zk: localhost:2181(CONNECTED) 14] ls /
[default, zkPro, zookeeper]
创建一般节点(无序、持久节点)
创建有序节点
get 命令来确认第二步中所创建的 znode 是否包含我们所创建的字符串
[zk: localhost:2181(CONNECTED) 15] get /zkPro
myData
set 节点
set 命令来对 zk 所关联的字符串进行设置
set [-s] [-v version] path data
[zk: localhost:2181(CONNECTED) 16] set /zkPro mydata123
每次修改数据之后,当前节点的数据版本号dataVersion会自增1
修改节点的值的时候,可以带上版本号,只有版本号与当前节点的数据版本号一致的时候才能修改成功
相当于乐观锁的机制,在多线程操作数据的情况下可以防止出现ABA问题
delete 节点
将刚才创建的 znode 删除
delete [-v version] path
[zk: localhost:2181(CONNECTED) 18] delete /zkPro
[zk: localhost:2181(CONNECTED) 19] ls /
[default, zookeeper]
可以加上版本号进行删除。
当删除的节点下存在子节点的时候,删除当前节点将会失败。需要使用 deleteall 删除,3.7版本之前是rmr命令
与更新节点类似,删除也可以传入版本号,当传入的dataVersion与当前版本号不一致时,zookeeper会拒绝删除
rmr 递归删除
要想删除某个节点及其后代节点
,可以使用递归删除
rmr path
节点信息的改变
cZxid:数据节点创建时的事务id
ctime:数据节点创建时的时间
mZxid:数据节点最后一次更新时的事务 id
没有改变之前(初始值)和 cZxid 一致,在节点发生过任何一次修改之后将会改变
mtime:数据节点最后一次更新时的时间
没有改变之前(初始值)和 ctime 一致,在节点发生过任何一次修改之后将会改变
pZxid:数据节点的子节点最后一次修改时的事务id
每一次当前节点的子节点时发生改变(创建或者修改),与最新创建或者修改时子节点的pZxid一致
cversion:子节点的更改次数
dataVersion:当前节点数据修改次数
aclVersion:节点的 ACL 修改次数(当前节点对应的权限列表修改次数)
ephemeralOwner:如果当前节点是临时节点,则表示创建该节点会话的 SessionID,如果当前节点是持久节点,则该属性为0
dataLength:数据内容的长度(字节为单位)
numChildren:数据节点当前的子节点个数
Java API操作zookeeper
Java API操作zookeeper需要引用下面的包
实现分布式配置中心
1 在zookeeper里增加一个目录节点
,并且把配置信息存储在里面
[zk: localhost:2181(CONNECTED) 20] create /username qinfeng
Created /username
2 创建一个 quickstart 的 maven 项目
,启动两个zookeeper客户端程序
/**
* 分布式配置中心demo
* @author
*
*/
public class MyZookeeper {
private static CountDownLatch connectedSemaphore = new CountDownLatch(1);
private static ZooKeeper zk = null;
private static Stat stat = new Stat();
public static void main(String[] args) throws Exception {
//zookeeper配置数据存放路径
String path = "/username";
//连接zookeeper并且注册一个默认的监听器
zk = new ZooKeeper("localhost:2181", 5000, //
new Watcher() {
@Override
public void process(WatchedEvent event) {
if (KeeperState.SyncConnected == event.getState()) { //zk连接成功通知事件
if (EventType.None == event.getType() && null == event.getPath()) {
connectedSemaphore.countDown();
} else if (event.getType() == EventType.NodeDataChanged) { //zk目录节点数据变化通知事件
try {
System.out.println("配置已修改,新值为:" + new String(zk.getData(event.getPath(), true, stat)));
} catch (Exception e) {
}
}
}
}
});
//等待zk连接成功的通知
connectedSemaphore.await();
//获取path目录节点的配置数据,并注册默认的监听器
System.out.println(new String(zk.getData(path, true, stat)));
Thread.sleep(Integer.MAX_VALUE);
}
}
两个程序启动后都正确的读取到了zookeeper的/username目录节点下的数据’qingfeng’
3 我们在zookeeper里修改下目录节点/username下的数据
[zk: localhost:2181(CONNECTED) 22] set /username qinfengyin
[zk: localhost:2181(CONNECTED) 23] get /username
qinfengyin
修改完成后,我们看见两个程序后台都及时收到了他们监听的目录节点数据变更后的值
,如下所示
Zookeeper集群模式安装
本例搭建的是伪集群模式,即一台机器上启动三个zookeeper实例组成集群,真正的集群模式无非就是实例IP地址不同,搭建方法没有区别
Step1:配置JAVA环境,检验环境:java -version
Step2:下载并解压zookeeper
# cd /usr/local
# wget http://mirror.bit.edu.cn/apache/zookeeper/stable/zookeeper-3.4.12.tar.gz
# tar -zxvf zookeeper-3.4.12.tar.gz
# cd zookeeper-3.4.12
Step3:重命名 zoo_sample.cfg文件
# cp conf/zoo_sample.cfg conf/zoo-1.cfg
Step4:修改配置文件zoo-1.cfg,原配置文件里有的,修改成下面的值,没有的则加上
# vim conf/zoo-1.cfg
dataDir=/tmp/zookeeper-1
clientPort=2181
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
配置说明
tickTime
:这个时间是作为Zookeeper 服务器之间
或客户端与服务器之间
维持心跳的时间间隔
,也就是每个 tickTime 时间就会发送一个心跳
。initLimit
:这个配置项是用来配置 Zookeeper 接受客户端
(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数
。当已经超过 10个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息
,那么表明这个客户端连接失败
。总的时间长度就是 10*2000=20 秒
syncLimit
:这个配置项标识Leader 与 Follower 之间发送消息
,请求和应答时间长度
,最长不能超过多少个 tickTime 的时间长度
,总的时间长度就是 5*2000=10秒dataDir
:顾名思义就是Zookeeper 保存数据的目录
,默认情况下,Zookeeper 将写数据的日志文件也保存在这个目录里
。clientPort
:这个端口就是客户端连接 Zookeeper 服务器的端口
,Zookeeper 会监听这个端口
,接受客户端的访问请求
。- server.A=B:C:D:其中
A 是一个数字,表示这个是第几号服务器
;B
是这个服务器的ip 地址
;C
表示的是这个服务器与集群中的 Leader 服务器交换信息的端口
;D
表示的是万一集群中的 Leader 服务器挂了
,需要一个端口来重新进行选举
,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口
。如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。
Step4:再从zoo-1.cfg复制两个配置文件zoo-2.cfg和zoo-3.cfg,只需修改dataDir和clientPort不同即可
# cp conf/zoo-1.cfg conf/zoo-2.cfg
# cp conf/zoo-1.cfg conf/zoo-3.cfg
# vim conf/zoo-2.cfg
dataDir=/tmp/zookeeper-2
clientPort=2182
# vim conf/zoo-2.cfg
dataDir=/tmp/zookeeper-3
clientPort=2183
Step5:标识Server ID
创建三个文件夹/tmp/zookeeper-1,/tmp/zookeeper-2,/tmp/zookeeper-2,在每个目录中创建文件myid 文件,写入当前实例的server id,即1.2.3
# cd /tmp/zookeeper-1
# vim myid
1
# cd /tmp/zookeeper-2
# vim myid
2
# cd /tmp/zookeeper-3
# vim myid
3
Step6:启动三个zookeeper实例
# bin/zkServer.sh start conf/zoo-1.cfg
# bin/zkServer.sh start conf/zoo-2.cfg
# bin/zkServer.sh start conf/zoo-3.cfg
Step7:检测集群状态
,也可以直接用命令“zkCli.sh -server IP:PORT
”连接zookeeper服务端检测
其他
可视化工具
github上有一个Swing开发的zooviewer项目,源码地址:https://github.com/HelloKittyNII/ZooViewer
运行环境
安装JDK,JDK版本>=1.8
执行
解压ZooViewer.zip,点击startup.bat,输入zookeeper的IP和端口,这里只需要输入zookeeper集群的一台服务器地址即可:
连接 集群内的zookeeper pod
,填入
pod_name.namespace.svc.cluster.local