ZooKeeper入门介绍
概述
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、分布式同步、集群管理、分布式事务等等。
ZooKeeper 由 Yahoo 开发,后来捐赠给了 Apache ,现已成为 Apache 顶级项目。ZooKeeper 是一个开源的分布式应用程序协调服务器,其为分布式系统提供一致性服务。其一致性是通过基于 Paxos 算法的 ZAB 协议完成的。
有关ZooKeeper的详细介绍可以阅读Guide哥对其的总结,因其实在写得太好,太详细我觉得我真的没必要再对其做重复的解释:
实战
通过以上的两篇文章了解了ZooKeeper的相关概念后,我们就可以通过Curator来操作ZooKeeper,完成一些我们想要实现的业务
比如我们想要使用ZooKeeper来做RPC框架的注册中心,那每一个服务上线的时候就会在ZooKeeper中创建一个临时节点,在这个临时节点里面保存该服务的下的ip prot 调用方式 等节点信息。因为临时节点绑定了session域,当服务下线的时候该临时节点也会在ZooKeeper中被删除,完成服务的动态上下线。当服务消费者需要进行服务调用的时候只需要通过服务名找到相应的服务地址信息,然后缓存到本地,再通过负载均衡算法从地址列表中选取一个服务提供者的地址调用就行了
除了注册中心,我们还可以使用ZooKeeper完成分布式锁等,想要完成以上的功能,都需要对ZooKeeper节点进行CRUD
1.通过Docker安装ZooKeeper
pull镜像
docker pull zookeeper:3.5.8
运行ZooKeeper
docker run -d --name zookeeper -p 2181:2181 zookeeper:3.5.8
2.使用Curator对节点进行CRUD
package cuit.epoch.pymjl.curatordemo.curator;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* @author Pymjl
* @version 1.0
* @date 2022/5/2 20:37
**/
@Slf4j
public class CreateConnection {
private static final String PATH = "/test/t2";
private static final String ROOT_PATH = "/test";
public static void main(String[] args) throws Exception {
/*
重试策略,重试3次且每次多1s
*/
ExponentialBackoffRetry exponentialBackoffRetry = new ExponentialBackoffRetry(1000, 3);
CuratorFramework zkClient = CuratorFrameworkFactory.builder()
// 若配置集群则是 ip1:port, ip2:post, ip3:port(,隔开)
.connectString("127.0.0.1:2181")
// 超时,也是心跳时间
.sessionTimeoutMs(50000)
.retryPolicy(exponentialBackoffRetry)
.build();
zkClient.start();
log.info("连接成功");
//查询子节点
log.info("开始查询子节点......");
List<String> s = zkClient.getChildren().forPath(ROOT_PATH);
for (String node : s) {
System.out.println(node);
}
//创建节点
log.info("开始创建新的持久节点");
//父节点不存在时递归创建,因为一次本来只能一个节点
zkClient.create().creatingParentContainersIfNeeded()
// 创建的节点类型,共有七种,注意临时节点不能有子节点
.withMode(CreateMode.PERSISTENT)
.forPath(PATH, "Hello world".getBytes(StandardCharsets.UTF_8));
//查询子节点
log.info("开始查询创建后的子节点列表......");
List<String> s2 = zkClient.getChildren().forPath(ROOT_PATH);
for (String node : s2) {
System.out.println(node);
}
//查询节点内容
log.info("开始查询创建后的节点内容");
byte[] bytes = zkClient.getData().forPath(PATH);
System.out.println(new String(bytes));
//修改节点内容
zkClient.setData().forPath(PATH, "update Hello world".getBytes(StandardCharsets.UTF_8));
//查询节点内容
log.info("开始查询更新后的子节点内容");
byte[] byte01 = zkClient.getData().forPath(PATH);
System.out.println(new String(byte01));
//删除节点
log.info("开始删除节点");
Stat stat = new Stat();
zkClient.getData().storingStatIn(stat).forPath(PATH);
zkClient.delete().withVersion(stat.getVersion()).forPath(PATH);
//查询子节点
log.info("开始查询删除节点后的子节点列表......");
List<String> s1 = zkClient.getChildren().forPath(ROOT_PATH);
for (String node : s1) {
System.out.println(node);
}
}
}
运行测试
