Zookeeper
概述
- Zookeeper本身是Apache提供的一套开源的用于进行分布式管理和协调的机制/框架。官网:https://zookeeper.apache.org
- Zookeeper本身提供了中心化服务,包含统一配置、统一命名、分布式锁服务、分布式组服务,更多的时候,Zookeeper充当了一个注册中心来使用
- Zookeeper是Yahoo!仿照了Google的<The Chubby Lock Service>开发的后来贡献给了Apache的一套框架
安装
概述
- 在大数据中,几乎所有的框架,它的安装都提供了三种模式
- 单机模式:在一台服务器上安装,往往能够启动这个框架的部分服务
- 伪分布式:在一台服务器上安装,但是利用多个线程模式分布式环境,能够启动这个框架的大部分甚至于服务
- 分布式:在集群上安装,能够启动这个框架的所有服务
- 现阶段,先安装单机模式,搞定所有的概念之后,再到集群中安装
安装JDK
-
Centos7.9中可能自带了OpenJDK,需要卸载移除掉
rpm -qa | grep -i jdk | xargs rpm -ev --nodeps
-
上课的时候要求,所有的软件安装包放在
/opt/presoftware
下,将软件安装在/opt/software
下cd /opt mkdir presoftware mkdir software
-
进入presoftware下,将JDK安装包上传到这个目录下
cd presoftware # 将安装包上传到这个路径下 rz
-
解压到software目录下
tar -xvf jdk-8u371-linux-x64.tar.gz -C /opt/software/
-
进入software目录下
cd /opt/software/ # 重命名 mv jdk1.8.0_371/ jdk1.8
-
在Linux中, 环境变量的配置有两个位置:
/etc/profile
和~/.bashrc
。无论哪一个路径,默认都会扫描/etc/profile.d
目录下的脚本文件,所以,配置环境变量一般是放在/etc/profile.d
# 需要在/etc/profile.d来脚本文件 touch /etc/profile.d/javahome.sh # 编辑脚本文件 vim /etc/profile.d/javahome.sh # 在文件中添加 export JAVA_HOME=/opt/software/jdk1.8 export PATH=$PATH:$JAVA_HOME/bin # 保存退出,生效 source /etc/profile.d/javahome.sh # 测试 javac -version # 或者 java -version
安装Zookeeper(单机模式)
-
将安装包上传到Linux上
cd /opt/presoftware/ rz
-
解压
tar -xvf apache-zookeeper-3.9.1-bin.tar.gz -C /opt/software/
-
重命名
cd /opt/software/ mv apache-zookeeper-3.9.1-bin/ zookeeper-3.9.1
-
配置环境变量
# 编辑文件 vim /etc/profile.d/zookeeperhome.sh # 在文件中添加 export ZOOKEEPER_HOME=/opt/software/zookeeper-3.9.1 export PATH=$PATH:$ZOOKEEPER_HOME/bin # 保存退出,生效 source /etc/profile.d/zookeeperhome.sh
-
配置Zookeeper
-
进入Zookeeper的配置目录
cd /opt/software/zookeeper-3.9.1/conf
-
修改配置
# 复制文件 - 注意:Zookeeper启动的时候默认会使用zoo.cfg中的配置 cp zoo_sample.cfg zoo.cfg # 编辑文件 vim zoo.cfg # 修改dataDir属性的值 dataDir=/opt/software/zookeeper-3.9.1/data
-
启动Zookeeper
zkServer.sh start
-
检查Zookeeper的状态
# 方式一: jps # 如果有QuorumPeerMain,那么表示Zookeeper在运行 # 方式二: zkServer.sh status
-
进入Zookeeper的客户端文章来源:https://www.toymoban.com/news/detail-842309.html
zkCli.sh
-
技术点
特点
- Zookeeper默认对外提供的客户端端口号是2181,可以通过
zoo.cfg
中的clientPort
属性来修改,但是不建议 - Zookeeper本身是一个树状结构,根节点是
/
- 不同于Linux的地方在于,Zookeeper中没有相对路径的说法,所有节点路径都必须从根节点开始计算
- 当Zookeeper启动的时候,自动的添加一个节点
/zookeeper
,存放的是Zookeeper本身的集群信息 - 在Zookeeper3.7及以前的版本中,要求每一个节点在创建的时候必须携带数据,这个数据可以是对节点的描述或者是配置信息
- 每一个节点携带的数据默认是在内存以及磁盘上
- 维系在内存的目的是为了读写快
- 维系在磁盘的目的是为了持久化
- 数据在磁盘上的存储路径默认由
dataLogDir
属性来控制,默认情况下,如果没有单独指定,dataLogDir
的属性值和dataDir
是一致的 - 临时节点下不能挂载子节点!
- Zookeeper会为每一次的写操作分配一个全局递增的编号,这个编号称之为事务id,简写为
Zxid
。一个节点刚被创建的时候,三个事务id是一致的
操作命令
命令 | 解释 |
---|---|
ls / |
查看跟节点的子节点 |
create /big |
在根节点下创建子节点big - 这种创建方式是从Zookeeper的3.8版本开始的 |
create /test 'this is a test server' |
在根节点下创建test节点,并且携带数据 |
create /data '' |
创建节点,并且给定数据为空 |
get /big |
获取节点的数据 |
set /video 'size=500M' |
修改数据 |
delete /test |
删除节点,要求节点为空(不能有子节点) |
rmr /video |
删除这个节点及子节点,从Zookeeper3.8开始,这个命令就过时了 |
deleteall /video |
删除这个节点及子节点,从Zookeeper3.8开始建议使用的命令 |
ls -w / |
监控指定节点的子节点的个数变化 - 只监控一次 |
get -w /news |
监控指定节点的数据是否变化 - 只监控一次 |
removewatches /news |
移除监控 |
history |
查看执行过的指令 |
redo 24 |
重新执行编号为24的命令 |
close |
关闭连接,但是没有退出Zookeeper客户端 |
quit |
直接退出客户端,需要通过zkCli.sh 重新进入 |
connect localhost:2181 |
连接本机的2181端口 |
getAllChildrenNumber / |
获取根节点以及所有子节点的数量 |
setquota -n 2 /news |
/news节点下的子节点个数最好不要超过2个 |
setquota -b 1024 /news |
/news节点的数据最好不要超过1024B |
listquota /news |
获取/news节点上的限制 |
delquota /news |
删除/news节点上的限制 |
version |
查看Zookeeper的版本 |
whoami |
查看当前的用户 |
sync / |
将根目录下的数据同步给其他的follower |
getEphemerals / |
获取根节点的临时节点 |
create -e /big '' |
创建临时节点 |
create -s /test/t '' |
创建持久顺序节点 |
create -e -s /test/t '' |
创建临时顺序节点 |
stat /news |
查看节点的属性/信息 |
节点类型
节点 | 解释 |
---|---|
Persistent | 持久节点 |
Ephemeral | 临时节点 |
Persistent_Sequential | 持久顺序节点 |
Ephemeral_Sequential | 临时顺序节点 |
节点信息/属性
属性/信息 | 解释 |
---|---|
cZxid | 这个节点创建对应的事务id,整个过程中第几个写操作创建了这个节点 |
ctime | 这个节点创建对应的时间 |
mZxid | 这个节点的数据修改对应的事务id,整个过程中第几个写操作修改了数据 |
mtime | 这个节点的数据修改对应的时间 |
pZxid | 这个节点的子节点个数变化对应的事务id,整个过程中第几个写操作导致这个节点的子节点个数产生了变化 |
cversion | 这个节点的子节点个数变化了几次 |
dataVersion | 这个节点的数据被修改了几次 - 数据版本 |
aclVersion | 这个节点的权限被修改了几次 |
ephemeralOwner | 如果是持久节点,此项值为0x0;如果是临时节点,此项值为当前的会话编号(sessionid) |
dataLength | 数据的长度(字节个数) |
numChildren | 子节点个数 |
API操作:使用java远程连接并操作Zookeeper文章来源地址https://www.toymoban.com/news/detail-842309.html
public class Demo1 {
ZooKeeper zk;
@Before //在所有@Test之前执行
public void connect() throws Exception {
/*CountDownLatch是一个同步工具类,它可以使一个或多个线程一直等待,直到其他线程的操作执行完为止。
在这段代码中,CountDownLatch的作用是等待ZooKeeper客户端连接到ZooKeeper服务器,直到连接事件被
触发并且状态为SyncConnected时,cdl.countDown() 被调用,才会继续往下执行。这可以保证在客户端连
接成功之前不会执行后续的操作,从而保证客户端在使用前已经处于连接的可用状态,有效避免操作失败的情况发生。
*/
/* 在这段代码中,主要涉及到两个线程:主线程和ZooKeeper内部使用的事件处理线程。
主线程负责执行connect()方法。
当主线程执行到cdl.await()时,会进入阻塞状态,等待CountDownLatch的计数器减为0。
ZooKeeper客户端会在另一个线程内部处理连接操作,并执行Watcher中的process()方法。
当ZooKeeper客户端连接成功后,通过调用cdl.countDown()方法将CountDownLatch的计数器减1。
主线程检测到CountDownLatch的计数器为0后,解除阻塞状态,继续执行后续代码。
因此,在这段代码中,主线程会在连接成功之前一直阻塞,直到ZooKeeper客户端连接成功并调用cdl.countDown()后,主线程才会继续执行。这样可以保证在确保连接建立之后再执行后续操作,避免因为连接未建立就开始操作而导致错误
*/
final CountDownLatch cdl = new CountDownLatch(1);
zk = new ZooKeeper("192.168.200.130:2181",
40000,
new Watcher() {
public void process(WatchedEvent watchedEvent) {
if (watchedEvent.getState() == Event.KeeperState.SyncConnected)
System.out.println("success");
cdl.countDown();
}
});
cdl.await();
}
@Test
public void createNode() throws Exception {
//参数: 节点路径 数据 权限 类型
// 返回值是节点路径() 如果是非顺序节点,这个返回值就是第一个路径参数.如果是顺序节点,那么当重名时,就会给节点路径加上序号来返回
String path = zk.create("/big", "data Server".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
}
@Test
public void get() throws KeeperException, InterruptedException {
//节点信息对象
Stat stat = new Stat();
//参数: 路径 监控 信息
byte[] data = zk.getData("/big", null, stat);
System.out.println(new String(data));
//这里的时间信息是Long 时间戳
System.out.println(stat);
}
@Test
public void modify() throws KeeperException, InterruptedException {
//这个版本必须和dataversion一致
//KeeperException$BadVersionException: KeeperErrorCode = BadVersion for /java_api
//防止产生ABA问题(理解ABA问题),确保修改的是最新的数据
//忽略掉版本校验 -1
Stat stat = zk.setData("/java_api", "data modify".getBytes(), 0);
System.out.println(stat);
}
@Test
public void delete() throws KeeperException, InterruptedException {
//忽略掉版本校验 -1
zk.delete("/big", -1);
}
@Test
public void getChidren() throws KeeperException, InterruptedException {
//没用到watcher ,给null
List<String> children = zk.getChildren("/", null);
for (String child : children) {
System.out.println(child);
}
}
@Test
public void exist() throws KeeperException, InterruptedException {
//忽略掉版本校验 -1
Stat stat = zk.exists("/java_api", null);
System.out.println(stat != null);
}
//监控节点是否发生改变
@Test
public void nodeDataChange() throws Exception {
CountDownLatch cdl = new CountDownLatch(1);
/* zk.getData("/test",event ->{
if(event.getType() == Watcher.Event.EventType.NodeDataChanged)
})*/
/* zk.getData("/test", event ->{
if(event.getType() == Watcher.Event.EventType.NodeDataChanged)
System.out.println("节点数据被修改");
cdl.countDown();
}, null);*/
zk.getData("/test", event -> {
if (event.getType() == Watcher.Event.EventType.NodeDataChanged)
System.out.println("节点数据被修改");
cdl.countDown();
}, null);
cdl.await();
}
@Test
public void nodeChildrenChange() throws Exception {
CountDownLatch cdl = new CountDownLatch(1);
zk.getChildren("/test", event -> {
if (event.getType() == Watcher.Event.EventType.NodeDataChanged)
System.out.println("节点数据被修改");
cdl.countDown();
});
// zk.getChildren("/test", new Watcher() {
// @Override
// public void process(WatchedEvent watchedEvent) {
//
// }
// })
}
@Test
public void nodeChange() throws Exception {
CountDownLatch cdl = new CountDownLatch(1);
zk.exists("/big", event -> {
if (event.getType() == Watcher.Event.EventType.NodeCreated)
System.out.println("节点被创建");
else if (event.getType() == Watcher.Event.EventType.NodeDeleted)
System.out.println("节点被删除");
cdl.countDown();
});
cdl.await();
}
}
到了这里,关于大数据培训之Zookeeper零基础-1的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!