Zookeeper(一)之基本概念及操作
Zookeeper(一)之基本概念及操作
Zookeeper(一)之基本概念及操作
引言
场景需求
简介
Apache ZooKeeper是Apache软件基金会的一个软件项目,它为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册。
简言:Zookeeper就是一个管理多个服务的
集群管理者
+文件系统
核心解决问题:
- 同步集群的配置信息(文件系统)
- 监听服务器的上下线,同时可以做出反应。(监听器)
特点
- 1主(Leader)多从(Follower),一旦故障就能立刻选出新的主机,继续提供服务。
自身稳定性No单点故障
- 集群中只要有半数以上zk节点存活,zk集群就能正常使用。
服务节点可靠性
- 选主和操作,使用
投票机制
。服务的高效性、可靠性、操作的可靠性
- 任何一台zk主机添加的数据,都会同步到所有zk主机。
全局数据同步
- zk数据更新要么全部成功,要么全部失败。
事务性,数据一致性
集群角色简介
leader(主机)是zookeeper集群的核心
- zookeeper集群工作的核心
- 事务操作的老大(增删改操作得让他点头)
follower(从机)
- 承担非事务性操作,读操作
- 参与leader选举的投票
observer(观察者,了解即可)
-
承担非事务性操作,读操作
-
不能参与leader选举的投票
投票选主流程
主机不固定,动态选举,保证主机的可靠性,选举过程中主从之间有通信
# 假设有5台服务器,编号1,2,3,4,5。
服务器1启动,给自己投票,接受在已经启动的机器队列中接受投票。得1票。
服务器2启动,给自己投票,接受在已经启动的机器队列中接受投票。得2票,但此时投票数没有大于半数,所以两个服务器的状态依然是(选举状态)。
服务器3启动,给自己投票,接受在已经启动的机器队列中接受投票,得3票,由于服务器3的编号最大所以服务器3胜出,此时投票数正好大于半数,所以服务器3成为leader,服务器1,2成为follower。
服务器4启动,已经有leader,服务器4只能成为follower。
服务器5启动,后面的逻辑同服务器4成为follower。
# zookeeper的作用
1.存数据,所有zookeeper节点同步数据。
2.监听器,服务器和数据变化,事件发生时可以做出反应(执行代码)。
3.zookeeper集群本身的稳定性、数据可靠性非常高。
4.zookeeper的客户端实际上是zk要管理的集群服务器(软件程序)。
5.zookeeper保存数据:服务器地址、状态、配置信息。(非常少量的数据)
基本使用
集群规划
Zookeeper安装
-
准备机器3台
0. 设置ip 1. 安装jdk 2. 配置java环境变量 3. 关闭防火墙 4. 设置hostname 5. 设置hosts(3台彼此之间集群互通)
-
解压
tar -zxvf zookeeper-3.4.14.tar.gz -C /opt/installs
-
配置path环境变量
export PATH=$PATH:$JAVA_HOME/bin:/opt/installs/zookeeper3.4.14/bin
source /etc/profile
-
初始化配置
-
在zookeeper下创建data文件夹
-
在conf目录下通过拷贝的方式创建zoo.cfg文件
-
配置zookeeper的文件存放位置
dataDir=/opt/install/zookeeper3.4.14/data
-
-
标记zk的主机号
在zk的data文件下创建
myid
文件,并指定一个zk主机编号,一般用ip为编号100
-
配置zk集群的节点信息
编辑zoo.cfg配置文件
server.zk号=ip:2888:3888 server.zk号=ip:2888:3888 server.zk号=ip:2888:3888
说明:
-
同步配置到所有zk在的宿主机上
scp -r ./zookeeper root@ip:/opt/installs/
-
修改每个机器上的myid
-
管理zk
- 启动
zkServer.sh start
- 查看状态
zkServer.sh status
- 停止
zkServer.sh stop
- 客户端
zkCli.sh
登录本机的zkzkCli.sh -server ip:2181
登录指定ip的zk主机
文件系统
Zookeeper维护一个
类似文件系统
的数据结构
- 每个节点就是一个文件。
- 每个节点都有一个名字一个值。
- 每个节点即可以是文件又可以是文件夹,下面可以继续挂节点。
# 1.客户端使用基本命令
1. 进入客户端
zkCli.sh
2. 查看帮助命令
[zk: localhost:2181(CONNECTED) 1] help
3. 退出客户端
[zk: localhost:2181(CONNECTED) 1] quit
# 2.数据管理命令
# 1. 浏览某个节点下的子节点(的名字)
ls /
# 2. 创建节点,并指定他的值。
[zk: localhost:2181(CONNECTED) 8] create /2nf "2nf"
Created /2nf
# 3. 查看节点的值
[zk: localhost:2181(CONNECTED) 10] get /2nf
2nf # 数据
cZxid = 0x200000005
ctime = Wed Nov 10 10:38:47 CST 2021 # 创建时间
mZxid = 0x200000005
mtime = Wed Nov 10 10:38:47 CST 2021
pZxid = 0x200000005
cversion = 0
dataVersion = 0 # 节点数据的更新次数【只要执行set就更新】
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 10 # 节点数据的字节,最大值1M
numChildren = 0 # 直接子节点的个数
# 4. 修改节点的值
[zk: localhost:2181(CONNECTED) 45] set /2nf "新值"
# 5. 删除节点
[zk: localhost:2181(CONNECTED) 53] delete /2nf
# 6. 删除节点及其子节点
[zk: localhost:2181(CONNECTED) 53] rmr /2nf
命令 | 含义 |
---|---|
ls / | 浏览某个节点下的子节点(名称) |
create /节点 “节点值” | 创建节点,并指定他的值 |
get /节点 | 查看节点的值 |
set /节点 “新值” | 修改节点的值 |
delete /节点 | 删除某个节点 |
rmr /节点 | 删除该节点,并递归删除内部所有节点 |
节点类型
# 节点类型
zookeeper可以将节点设置不同的类型
1. 持久化节点
节点只要不删除,会一直存在。
2. 顺序编号节点
每次对相同节点,重复创建,会自动对znode名称进行编号。
3. 临时节点
客户端断开,则节点消失。
节点名称 | 中文 | 含义 |
---|---|---|
PERSISTENT | 持久化节点 | 客户端与zookeeper断开连接后,该节点依旧存在。 |
PERSISTENT_SEQUENTIAL | 持久化顺序编号节点 | 客户端与zookeeper断开连接后,该节点依旧存在, 只是zookeeper给该节点名称进行顺序编号。 |
EPHEMERAL | 临时节点 | 客户端与zookeeper断开连接后,该节点被删除。 |
EPHEMERAL_SEQUENTIAL | 临时顺序编号节点 | 客户端与zookeeper断开连接后,该节点被删除, 只是zookeeper给该节点名称进行顺序编号。 |
命令 | 含义 |
---|---|
create /节点 “节点值” | 持久化节点 |
create -s /节点 “节点值” | 持久化节点+顺序编号节点 |
create -e /节点 “节点值” | 临时节点,客户端断开连接则失效 |
create -s -e /节点 “节点值” | 顺序编号节点+临时节点 |
zookeeper命名服务案例
监听通知
- 监听节点值的修改(set)和删除(delete)变化
- 监听某个节点及其子节点的增加、删除
命令 | 含义 |
---|---|
get /节点1/节点2 watch | 查看节点内容,并监听该值的变化(修改、失效等) |
ls /节点 watch | 查看某个节点下的所有节点信息,并监听节点下的变化(添加删除子节点) |
Java访问Zookeeper
0. 依赖导入和log4j日志
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
1. 连接zookeeper
//1. 准备参数
String zkClusters = "192.168.242.20:2181,192.168.242.21:2181,192.168.242.22:2181";
//2. 创建zk客户端
zkClient = new ZkClient(zkClusters);
2. 文件系统相关
1. 获得子节点
//获得某个节点下的子节点。
List<String> children = zkClient.getChildren("/");
//遍历子节点下的节点。
for (String child : children) {
List<String> grandChildren = zkClient.getChildren("/" + child);
if (grandChildren.size()>0){
System.out.println(grandChildren);
}
}
2. 判断节点是否存在
// 判断节点是否存在
boolean exists = zkClient.exists("/2nf");
3. 添加
//创建持久化节点
String path = zkClient.create("/clusters", "jetty集群", CreateMode.PERSISTENT);
//创建临时节点
zkClient.create("/clusters/jetty1", "jetty1", CreateMode.EPHEMERAL);
//创建临时有序节点
//客户端断开连接:zkClient.close() 和超时30s都会断开连接
String path = zkClient.create("/clusters", "jetty集群", CreateMode.EPHEMERAL_SEQUENTIAL);
//创建持久有序节点
zkClient.create("/2nf/aries","第二范式",CreateMode.PERSISTENT_SEQUENTIAL);
4. 修改
zkClient.writeData("/clusters/jetty1","192.168.242.20");
//修改并获得操作的版本号(-1表示操作最新的数据版本号)
Stat stat = zkClient.writeDataReturnStat("/clusters/jetty1", "jetty", -1);
stat.getVersion();//数据操作版本号,每更新一次,就增加一次版本。
5. 删除
//递归删除,适合删除文件夹类节点
boolean delete = zkClient.deleteRecursive("/clusters");
//删除节点
boolean delete = zkClient.delete("/clusters/jetty1");
6. 读取
// 读取单节点信息
Object o = zkClient.readData("/clusters");
3. 监听服务相关
1. 监听单节点
监听节点值的修改和节点删除
zkClient.subscribeDataChanges("/clusters", new IZkDataListener() {
public void handleDataChange(String s, Object o) throws Exception {
System.out.println("节点:"+s);
System.out.println("新值:"+o);
}
public void handleDataDeleted(String s) throws Exception {
System.out.println("删除节点:"+s);
}
});
2. 监听子节点
监听子节点的变化(增删)
zkClient.subscribeChildChanges("/clusters", new IZkChildListener() {
public void handleChildChange(String s, List<String> list) throws Exception {
System.out.println("节点:"+s);
System.out.println("子节点:"+list);
}
});
分布式ID生成器
/**
* 分布式ID生成器
*/
public class GlobalID {
private String zkCluster;
private ZkClient zkClient;
private String tableName;
private String rootPath;
public GlobalID(String zkCluster, String tableName, String rootPath) {
this.zkCluster = zkCluster;
this.zkClient = new ZkClient(zkCluster);
this.tableName = tableName;
this.rootPath = rootPath;
}
public void init() {
//判断rootPath是否存在,不存在就创建
boolean isExistedRoot = zkClient.exists(rootPath);
if (!isExistedRoot) {
zkClient.create(rootPath, "id生成器的根目录", CreateMode.PERSISTENT);
}
//判断tableName是否存在,不存在就创建
boolean isExistedTable = zkClient.exists(rootPath + "/" + tableName + "_id");
if (!isExistedTable) {
zkClient.create(rootPath + "/" + tableName + "_id", "id生成器", CreateMode.PERSISTENT);
}
}
public int generateId() {
//使用writeDataReturnStat()方法版本号的方式获取自增ID
Stat stat = zkClient.writeDataReturnStat(rootPath + "/" + tableName + "_id", "", -1);
return stat.getVersion();
}
}
Zookeeper的集群zkServer服务个数
2N+1个
原因:3台zkServer的稳定性要大于4台。 1台的稳定性大于2台的稳定性。
更多推荐
所有评论(0)