提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
Zookeeper的使用
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
提示:这里可以添加本文要记录的大概内容:
在如今的数据驱动时代,分布式系统已经成为企业和组织处理大规模数据和提供高可靠性服务的重要手段。而 Zookeeper 作为一种分布式协调服务框架,在分布式系统中扮演着关键的角色。
Zookeeper 提供了一个简单而强大的机制来管理分布式应用程序的状态。它通过提供一个共享的注册表,使得分布式系统中的各个节点可以协调彼此的行为,实现一致性、可靠性和可伸缩性。
在这篇博客中,我将深入探讨 Zookeeper 的核心概念、功能和应用场景。我们将了解 Zookeeper 如何实现配置管理、命名服务等重要功能。我还将分享一些实际的使用案例,展示 Zookeeper 在大规模分布式系统中的优势和价值。
无论是你是分布式系统的开发者、架构师还是运维人员,了解和掌握 Zookeeper 的使用都是至关重要的。通过合理利用 Zookeeper,你将能够构建更加可靠、高效和可扩展的分布式应用。
让我们一起探索 Zookeeper 的世界,掌握其强大的功能,为你的分布式系统架构带来新的可能性!
提示:以下是本篇文章正文内容,下面案例可供参考
Zookeeper 是一种开源的分布式协调服务框架,它提供了一个高性能、高可用的分布式数据管理和协调平台。Zookeeper 最初是由 Yahoo! 开发的,并于 2010 年成为 Apache 软件基金会的顶级项目。
Zookeeper 的设计目标是解决分布式应用程序中常见的协调问题,如服务发现、领导选举、配置管理、分布式锁等。它通过维护一个树形结构的目录来存储和管理分布式应用程序的状态信息。
Zookeeper 的核心特性包括:
Zookeeper 通常以集群的形式部署,由多个节点组成,其中一个节点被选举为领导者(Leader),其他节点为追随者(Follower)。领导者负责处理客户端的请求,并将数据同步到追随者节点。
Zookeeper 被广泛应用于各种分布式系统中,如 Hadoop、Kafka、HBase 等。它为分布式应用程序提供了一个可靠的基础设施,使得开发和管理分布式系统变得更加简单和可靠。
如果你对 Zookeeper 感兴趣,我建议你进一步了解它的工作原理、应用场景和实际使用案例。通过深入学习,你将能够更好地利用 Zookeeper 来构建和管理高性能、可靠的分布式系统。
注意:Zookeeper=文件系统+监听机制
1.下载Zookeeper压缩包点击这里
2.解压zookeeper
tar -zxvf apache-zookeeper-3.7.3.tar.gz -C /usr/local
3.修改配置文件,进入zookeeper的安装目录的conf目录
cd /usr/local/zookeeper/config
cp zoo_sample.cfg zoo.cfg
4.修改zoo.cfg
# The number of milliseconds of each tick
tickTime=2000initLimit=10
syncLimit=5
dataDir=/usr/local/zookeeper/zkdata
dataLogDir=/usr/local/zookeeper/zklogs
clientPort=2181
5.创建数据持久化目录
mkdir /usr/local/zookeeper/zkdata
mkdir /usr/local/zookeeper/zklogs
6.配置JDK环境,vim /etc/profile
export JAVA_HOME=/usr/local/jdk
export PATH=$PATH:$JAVA_HOME/bin
7.生效环境变量
source /etc/profile
8.启动zookeeper服务
zkServer.sh start
9.查看Zookeeper运行状态
zkServer.sh status
1.环境准备
服务器1 192.168.66.101
服务器2 192.168.66.102
服务器3 192.168.66.103
2.解压zookeeper
tar -zxvf apache-zookeeper-3.6.3.tar.gz -C /usr/local
3.修改配置文件,进入zookeeper的安装目录的conf目录
cd /usr/local/zookeeper/config
cp zoo_sample.cfg zoo.cfg
4.修改zoo.cfg
# 心跳检查的时间 2秒
tickTime=2000initLimit=10
# ZK Leader 和follower 之间通讯的次数,总时间5*2=10秒
syncLimit=5
# 存储内存中数据快照的位置,如果不设置参数,更新事务日志将被存储到默认位置。
dataDir=/usr/local/zookeeper/zkdata
# ZK 服务器端的监听端口
clientPort=2181
#autopurge.purgeInterval=1
server.1=192.168.66.101:2888:3888
server.2=192.168.66.102:2888:3888
server.3=192.168.66.103:2888:3888
5.创建数据持久化目录,对3台节点,都创建zkdata目录 。
mkdir /usr/local/zookeeper/zkdata
7.在工作目录中生成myid文件
第一台机器上: echo 1 > /usr/local/zookeeper/zkdata/myid
第二台机器上: echo 2 > /usr/local/zookeeper/zkdata/myid
第三台机器上: echo 3 > /usr/local/zookeeper/zkdata/myid
8.启动zookeeper集群,zookeeper没有提供自动批量启动脚本,需要手动一台一台地起zookeeper进程 在每一台节点上,运行命令:
bin/zkServer.sh start
在Zookeeper中,可以说 Zookeeper中的所有存储的数据是由znode组成的,节点也称为 znode,并以 key/value 形式存储数据。以 key/value 形式存储数据。key就是znode的节点路径,比如 /java , /server。
ZooKeeper 节点是有生命周期的,这取决于节点的类型。节点类型可以分为持久节点、临时节点,以及时序节点,具体在节点创建过程中,一般是组合使用,可以生成以下 4 种节点类型。
持久节点是zookeeper中最常见的一种节点类型。所谓持久节点,是指改数据节点被创建后,就会一直存在与zookeeper服务器上,直到有删除操作来主动清除这个节点。示例:
/java spring
/zhangsan zhangsan
这类节点的基本特性和上面的节点类型是一致的。额外的特性是,在ZK中,每个父节点会为他的第一级子节点维护一份时序,会记录每个子节点创建的先后顺序。示例:
/java00000000000001 spring
/baizhan00000000000001 itbaizhan
从名称上可以看出该节点的一个最重要的特性就是临时性。所谓临时性是指,如果将节点创建为临时节点,那么该节点数据不会一直存储在 ZooKeeper 服务器上。
注意:和持久节点不同的是,临时节点的生命周期和客户端会话绑定。也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉。注意,这里提到的是会话失效,而非连接断开。另外,在临时节点下面不能创建子节点。
临时顺序节点的基本特性和临时节点是一致的,同样是在临时节点的基础上,添加了顺序的特性。示例:
/baizhan0000000000000001 zhangsan
/baizhan0000000000000002 zhangsan
/baizhan0000000000000003 zhangsan
创建ZK节点,语法结构:
create [-s] [-e] path data acl
示例:
[zk: localhost:2181(CONNECTED) 0]create /zk-book baizhan
读取节点信息ls命令和get命令,ls命令是显示节点下有哪些子节点,而get命令是查看具体节点的数据。
语法结构:
ls path [watch]
示例;
ls /
使用get命令,可以获取zookeeper指定节点的数据内容和属性信息。
语法格式:
get path [watch]
示例:
get /zk-book
使用set命令,可以更新指定节点的数据内容。
语法结构:
set path data [version]
删除zookeeper上的指定节点。
语法结构:
delete path [version]
示例:
create /zk-book 123
create /zk-book/child 12345
delete /zk-book
ZooKeeper 提供了分布式数据的发布/订阅功能。一个典型的发布/订阅模型系统定义了一种一对多的订阅关系,能够让多个订阅者同时监听某一个主题对象,当这个主题对象自身状态变化时,会通知所有订阅者,使它们能够做出相应的处理。
语法结构:ls -w path
语法结构:get -w path
需要注意的是:watch监听机制只能够使用一次,如果下次想要使用,必须重新监听,就比如ls path watch命令,只能监听节点路径的改变一次,如果还想监听,那么需要再执行一次ls path watch命令。
Zookeeper 中的 ACL(访问控制列表)用于控制对 Znode 节点的访问权限。它可以定义不同的权限,如读、写、完全控制等。ACL 可以设置到 Znode 节点上,这样只有具有相应权限的客户端才能访问该节点。
语法格式:setAcl path Schema:ID:Permission
Schema可选参数如下:
方案 | 描述 |
---|---|
world | 只有一个用户:anyone,代表所有人(默认) |
ip | 使用IP地址认证 |
auth | 使用已添加认证的用户认证 |
digest | 使用“用户名:密码”方式认证 |
ID可选参数如下:
权限模式 | 授权对象 |
---|---|
IP | 通常是一个IP地址或是IP段,例如“192.168.66.101” |
Digest | 自定义,通常是“username:BASE64(SHA-1(username:password))” |
World | 只有一个ID:“anyone” |
Super | 与Digest模式一致 |
Permission可选参数如下:
项目 | Value |
---|---|
c | 可以创建子节点 |
d | 可以删除子节点(仅下一级节点) |
r | 可以读取节点数据及显示子节点列表 |
w | 可以设置节点数据 |
a | 可以设置节点访问控制列表权限 |
权限相关语法/命令:
命令 | 注释 |
---|---|
getAcl | 读取ACL权限 |
setAcl | 设置ACL权限 |
addauth | 添加认证用户 |
语法格式:setAcl
示例:
[zk: localhost:2181(CONNECTED) 0] create /node1 1
Created /node1
[zk: localhost:2181(CONNECTED) 1] getAcl /node1
'world,'anyone #默认为world方案
: cdrwa #任何人都拥有所有权限
语法格式:setAcl
示例:
#创建节点
[zk: localhost:2181(CONNECTED) 0] create /node2 1
Created /node2
#设置权限
[zk: localhost:2181(CONNECTED) 1] setAcl /node2 ip:192.168.100.1:cdrwa #设置IP:192.168.66.101 拥有所有权限
cZxid = 0x1900000239
#使用IP非 192.168.66.101 的机器
[zk: localhost:2181(CONNECTED) 0] get /node2
Authentication is not valid : /node2 #没有权限
语法格式:setAcl
示例:
1.添加认证用户
addauth digest <user>:<password>
2.授权
#创建节点
[zk: localhost:2181(CONNECTED) 0] create /node3 1
Created /node3
#添加认证用户
[zk: localhost:2181(CONNECTED) 1] addauth digest zhangsan:123456
#设置权限
[zk: localhost:2181(CONNECTED) 2] setAcl /node3 auth:yoonper:cdrwa
#获取权限
[zk: localhost:2181(CONNECTED) 3] getAcl /node3
'digest,'zhangsan:UvJWhBril5yzpEiA2eV7bwwhfLs=
: cdrwa
语法结构:setAcl
1.这里的密码是经过SHA1及BASE64处理的密文,在SHELL中可以通过以下命令计算:
echo -n <user>:<password> | openssl dgst -binary -sha1 | openssl base64
2.先来计算一个密文
echo -n baizhan:123456 | openssl dgst -binary -sha1 | openssl base64
UvJWhBril5yzpEiA2eV7bwwhfLs=
3.授权
#创建节点
[zk: localhost:2181(CONNECTED) 0] create /node4 1
Created /node4
#使用是上面算好的密文密码添加权限:
[zk: localhost:2181(CONNECTED) 1] setAcl /node4
digest:zhangsan:UvJWhBril5yzpEiA2eV7bwwhfLs=:cdrwa
#获取节点数据没有权限
[zk: localhost:2181(CONNECTED) 3] get /node4
Authentication is not valid : /node4
#添加认证用户
[zk: localhost:2181(CONNECTED) 4] addauth digest zhangsan:123456
#成功读取数据
[zk: localhost:2181(CONNECTED) 5] get /node4
1
引入依赖
<dependencies>
<dependency>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
<version>3.4.8version>
dependency>
dependencies>
/**
* 创建一个 Zookeeper 的实例
* 此处为一个集群,Zookeeper 的 ip 之间用逗号隔开
*
* 参数解释:
* param 1 - Zookeeper 的实例 ip ,此处是一个集群,所以配置了多个 ip,用逗号隔开
* param 2 - session 过期时间,单位秒 (1000)
* param 3 - 监视者,用于获取监听事件 (MyWatch)
*/
ZooKeeper zooKeeper = new ZooKeeper("192.168.1.108:2181", 5000, watcher);
private void createNodeSync() throws KeeperException, InterruptedException {
String path = "/poype_node";
/*
*znode名称
*节点数据
*设置权限
*znode类型
*
*/
String nodePath = zooKeeper.create(path, "123".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(nodePath);
}
znode的四种类型:
private void deleteSync() throws KeeperException, InterruptedException {
zooKeeper.delete("/node_1", 12);
}
/*
*znode名称
*节点数据
*该节点的版本
*/
Stat stat = zooKeeper.setData("/poype_node2", "poype5211314".getBytes(), 1);
private void existSync() throws KeeperException, InterruptedException {
/*
*znode 名称 (/zoo)
*监视者,用于获取监控事件 (MyWatch)
*/
Stat stat = zooKeeper.exists("/poype_node2", true);
System.out.println(stat);
}
通过zkCli.getchildren(“/”,new watch()){}来注册监听,监听的是整个根节点,但是这个监听只能监听一次。线程休眠是为了让监听等待事件发生,不然会随着程序直接运行完。
public class WatchDemo1 {
static List<String> children = null;
public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
ZooKeeper zkCli = new ZooKeeper("192.168.50.183:2181,192.168.50.184:2181,192.168.50.185:2181", 3000, new Watcher() {
//监听回调
@Override
public void process(WatchedEvent event) {
System.out.println("正在监听中.....");
}
});
//监听目录
children = zkCli.getChildren("/", new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println("监听路径为:" + event.getPath());
System.out.println("监听的类型为:" + event.getType());
System.out.println("数据被2货修改了!!!");
for(String c:children) {
System.out.println(c);
}
}
});
Thread.sleep(Long.MAX_VALUE);
}
}
getData监听的为一个节点,同样只监听一次,返回的是该节点的内容。
public class WatchDemo {
public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
ZooKeeper zkCli = new ZooKeeper("192.168.50.183:2181,192.168.50.184:2181,192.168.50.185:2181", 3000, new Watcher() {
//监听回调
@Override
public void process(WatchedEvent event) {
}
});
byte[] data = zkCli.getData("/hunter", new Watcher() {
//监听的具体内容
@Override
public void process(WatchedEvent event) {
System.out.println("监听路径为:" + event.getPath());
System.out.println("监听的类型为:" + event.getType());
System.out.println("数据被2货修改了!!!");
}
}, null);
System.out.println(new String(data));
Thread.sleep(Long.MAX_VALUE);
}
}
zkclient是Github上一个开源的Zookeeper客户端,在Zookeeper原生 API接口之上进行了包装,是一个更加易用的Zookeeper客户端。同时Zkclient在内部实现了诸如Session超时重连,Watcher反复注册等功能,从而提高开发效率。
添加依赖
<dependency>
<groupId>com.101tecgroupId>
<artifactId>zkclientartifactId>
<version>0.10version>
dependency>
String connStr = "192.168.66.101:2181";
ZkClient zk = new ZkClient(connStr);
String res = zk.create("/root", "baizhan", CreateMode.PERSISTENT);
zk.writeData("/root", "itbaizhan");
String res = zk.readData("/root");
zk.delete("/root");
zk.subscribeDataChanges("/root/ghz", new IZkDataListener() {
@Override
public void handleDataDeleted(String arg0) throws Exception {
System.err.println("数据删除:" + arg0);
}
@Override
public void handleDataChange(String arg0, Object arg1) throws Exception {
System.err.println("数据修改:" + arg0 + "------" + arg1);
}
});
zk.subscribeChildChanges("/root", (arg0, arg1) -> {
System.err.println("子节点发生变化:" + arg0);
arg1.forEach(f -> {
System.out.println("content:" + f);
});
});
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了Zookeeper的使用,如果大家有什么疑问可以在评论区提出。