1. 什么是zookeeper?
zookeeper 是一个分布式协调应用程序,通常以集群的方式对外工作。提供服务注册、服务发现和心跳检测。
2. zookeeper核心的数据结构?
zookeeper服务端内部是维护一个树形的结构,类似文件系统。每个树形节点就是一个Znode。该数据模型是在内存中维护的,正因为如此,才实现了高性能的目的。
zookeeper客户端和服务端通过一个session进行连接,客户端可以通过session对服务端维护的树形数据结构进行操作,及操作那些节点Znode.
zookeeper 包含四类节点:
1) 持久节点 :当会话结束后,节点不会被删除。
2)持久顺序节点 :当会话结束后,节点不会被删除,且节点名中带自增数后缀
3)临时节点 : 当会话结束后,该节点将会被删除
4)临时顺序节点 : 当会话结束后,该节点会被删除,且节点名中自带自增数后缀
PS: 只有持久性节点和持久顺序节点才能有子节点!!
3. zookeeper 集群是怎么样的?
zookeeper集群包含多个节点,每个节点对应一台zookeeper服务器,所有的节点共同对外服务。
zookeeper 集群自身采用的是一种轻量级的分布式一致性协议,名为Zab。Zab协议分为两个阶段,分别为是领导选举阶段和原子广播阶段。
当zookeeper集群启动的时候,将会选举一台节点为leader,其他的节点则为follower。当leader节点出现问题的时候,会自动选举出新的leader节点,让所有的几点恢复到正常状态,这是领导选举阶段。
领导选举阶段结束后,就进入原子广播阶段,这个阶段会同步leader节点和各个follower节点之间的数据,确保leader和follower节点具有相同的状态。
所以的写操作都会发送到leader节点,并通过广播的方式将数据同步到其他的follower节点。
zookeeper集群中只要有半数以上的节点存活,节点就可以对外正常工作。所以一般集群的节点为奇数个3,5个。当客户端连接的服务端节点出现故障时,会自动重新连接到其他的服务端节点。
4. zookeeper 的配置文件 conf/zoo.cfg
配置文件配置项
tickTime=2000 : tickTime 称为“滴答时间”,用于配置zookeeper中最小时间单元的长度。
initLimit=10 : initLimit 用于配置leader节点等待follower节点启动并完成数据同步的时间。这里=10表示10*tickTime
syncLimit=5 : syncLimit 用于配置leader节点和follower节点之间进行心跳检测的最大延时时间。超时则认为该follower节点脱离了leader的同步。
dataDir=/tmp/zookeeper : dataDir 用于配置zookeeper服务器存储快照文件的目录,不建议放到tmp目录下,可能会被自动删除。在集群环境下,将生成名为myid的文件,此文件存放zookeeper集群几点的ID。集群环境下,此ID是唯一的。
clientPort=2181 : clientPort 用于配置当前zookeeper服务器对外暴露的端口,客户端通过该端口连接zookeeper并创建会话。
其他配置项可参考zookeeper管理员手册
5. zookeeper 脚本程序使用
zookeeper安装目录的bin目录下是zookeeper提供的脚本。
zkServer.sh 脚本可传入以下参数
start : 用于后台启动zookeeper服务器
start-foreground : 用于前台启动zookeeper服务器
stop : 用于停止zookeeper服务器
restart : 用于重启 zookeeper 服务器
status : 用于获取zookeeper服务器的运行状态
upgrade : 升级zookeeper服务器
print-cmd : 用于打印出zookeeper程序命令行及其相关参数
windows 环境直接启动 zkServer.cmd
> zkServer.sh 用来启动zookeeper服务器
> zkCli.sh 用来连接zookeeper服务器的命令行客户端
> zkCleanUp.sh 用来清理zookeeper的历史数据,包括事务日志问价和快照数据文件
> zkEnv 用来设置zookeeper的环境变量
6. zookeeper 集群搭建
集群模式需要多台机器,可以在本地通过不同的端口搭建伪集群模式来进行测试。本质上是一样的。下面以搭建三个节点的伪集群为例。
1) 配置第一个节点 ,更改第一个节点的配置文件 zoo.cfg 如下:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper
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
这里在单机模式之外增加了 server 配置,这里表示该集群配置了3个节点。
注意server的配置需要满足一定的格式 server.
id : 表示节点的编号,表示该节点在集群中的唯一编号,取值范围是1~255之间的整数。
ip : 表示节点所在的IP地址
port1 : 表示leader节点和follower节点进行心跳检测与数据同步时所使用的端口
port2 : 表示进行领导选举过程,用于投票通信的端口
PS:这里因为是伪集群,所以每个节点的clientPort,port1,port2不可以配置为一样的。但是在实际真实的集群环境中,同类型的端口可以配置一样。
2) 配置第二个节点,更改第二个节点的配置文件 zoo.cfg 如下:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper1
clientPort=2182
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
3) 配置第三个节点,更改第三个节点的配置文件 zoo.cfg 如下:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zookeeper2
clientPort=2183
server.1=127.0.0.1:2888:3888
server.2=127.0.0.1:2889:3889
server.3=127.0.0.1:2890:3890
4) 特别注意:配置完三个节点之后,每个节点对应dataDir指定目录下需要创建一个名为myid的文件,其内容为该节点的编号。
例如,针对第一个节点,我们需要创建一个 /tmp/zookeeper/myid 的文件,该文件的内容为 1 ,其他的节点也需要同样的操作。
5) 上述工作完成之后,启动所有的zookeeper节点即可构成集群。可以使用telnet命令查看ip和端口,验证搭建的集群是否有效。
7. 使用命令行客户端连接 zookeeper
1) 连接zookeeper
本地连接 zkCli.sh(zkCli.cmd)
远程连接 zkCli.sh -server
2) zookeeper 客户端命令大部分是针对ZNode节点进行操作的。
help : 列出zookeeper客户端相关的命令提示
几个常用的客户端命令
> ls path [watch] :使用 ls 命令列出子节点的名称,命令中可设置一个watch参数,用于指定客户端监视器。默认情况下,根目录有一个名为 zookeeper的子节点,作为zookeeper的保留节点。一般不直接使用
> ls2 path [watch] : 以更加详细ide方式列出节点名称及其他信息
> stat path [watch] : 查看节点的stat信息,也可以用来判断节点是否存在
> create [-s] [-e] path data acl
. -s 选项用于指定该节点是否为顺序节点
. -e 选项用于指定该节点是否为临时节点
最后一个 acl 参数用于权限控制,zookeeper内部提供了一个强大的访问控制列表,默认情况下不做任何权限控制
举例:create /foo hello 创建一个/foo节点,该节点包含数据为hello的字符串
> get path [watch] : 获取节点的数据 如 get /foo
> set path data [version] : 更新节点数据
version 参数表示节点所包含数据的版本号。由于zookeeper会保存节点在不同版本下的数据。因此我们可以设置指定的版本号.如果不带版本号,则使用最新的版本
> delete path [version] : 删除节点,只能删除不存在子节点的节点
> rmr path : 删除节点和下面所有的子节点
8. 使用 java 客户端连接 zookeeper
1) 引入zookeeper java客户端jar包
2) 创建 zookeeper对象,用于调用zk的API进行操作
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import java.util.concurrent.CountDownLatch;
public class ZookeeperDemo {
private static final String CONNECTION_STRING = "127.0.0.1:2181";
private static final int SESSION_TIMEOUT = 5000;
private static CountDownLatch latch = new CountDownLatch(1);
public static void main(String[] args) throws Exception {
//连接zookeeper
ZooKeeper zk = new ZooKeeper(CONNECTION_STRING, SESSION_TIMEOUT, new Watcher() {
public void process(WatchedEvent watchedEvent) {
if(watchedEvent.getState() == Event.KeeperState.SyncConnected){
latch.countDown();
}
}
});
latch.await();
System.out.println(zk);
}
}
3) zk对象的API
> getChildren 列出子节点
> exists 判断节点是否已存在
> create 创建节点
> getData 获取节点数据
> setData 跟新节点数据
> delete 删除节点
zookeeper 官方提供了两套java客户端的API,即同步和异步,可根据需要选择合适的方式。