文章目录
图片素材均来源于百度图库
一、概述
1. 介绍
Zookeeper 简称 zk ,是一个分布式协调服务开源框架,主要用来解决分布式集群中应用系统的一致性问题。zk本质上是一个分布式的小文件存储系统,提供基于类似文件系统的目录树方式的数据存储,并且对树中的节点进行有效管理,从而来维护和监控存储的数据的状态变化,通过监控这些数据状态的变化,可以达到基于数据的集群管理。如:统一命名服务,分布式配置管理,分布式消息队列,分布式锁,分布式协调等
2. 架构模型
-
Leader:
主节点,zk 集群工作的核心,事务请求(写操作)的唯一调度和处理者,保证集群事务处理的顺序性,集群内部各个服务器的调度者。对于 create,setData,delete 等有写操作的请求,则需要统一转发给leader处理,leader 需要决定编号、执行操作,这个过程称为一个事务
-
Follower:
从节点,处理客户端非事务(读操作)请求,转发事务请求给 Leader,参与集群 Leader 选举投票,2n-1 台可以做集群投票
-
Observer:
观察者角色,观察 ZooKeeper 集群的最新状态变化并将这些状态同步过来,对于非事务请求可以进行独立处理,对于事务请求则会转发给 Leader 服务器进行处理。不参与 Leader 选举投票
3. zk的基本特性
-
全局数据一致:
每个 server 保存一份相同的数据副本,client 无论连接到哪个 server,展示的数据都是一致的
-
可靠性:
如果消息被其中一台服务器接收,那么将被所有服务器接收
-
顺序性:
在一台服务器上,消息a在消息b前发布,则在所有 server 上消息 a 都将在消息 b 前被发布;消息b在消息a后被同一个发送者发布,消息 a 必将排在消息 b 前面
-
数据更新原子性:
一次数据更新要么成功,要么失败,不存在中间状态
-
实时性:
zk 保证客户端将在一个时间间隔范围内获得服务器的更新信息,或者服务器失效的信息
二、安装
zk 集群搭建为了保证 Leader 选举(基于 Paxos 算法的实现)能够得到多数的支持,通常由 2n+1 台 servers 组成,所以集群的数量一般为奇数;依赖 java 环境,提前安装jdk,并配置 java 环境变量
1. 版本
软件名称 | 版本 |
---|---|
CentOS | 7.9 |
JDK | 1.8.0_181 |
Zookeeper | 3.5.7 |
2. 集群规划
服务器 | 服务 |
---|---|
h1 | JDK,ZK |
h2 | JDK,ZK |
h3 | JDK,ZK |
3. 安装
3.1 前置安装
3.2 安装Zookeeper
在h1上操作
cd /app/software/
#1、上传安装包
rz -E #选择apache-zookeeper-3.5.7-bin.tar.gz
#2、解压到/app
tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz -C /app
#3、重命名
cd /app
mv apache-zookeeper-3.5.7-bin/ zookeeper-3.5.7/
#4、创建配置文件
cd zookeeper-3.5.7
mkdir zkData
cd zkData
vim myid
##内容:
1
##
#5、配置zoo.cfg文件
cd /app/zookeeper-3.5.7/conf
mv zoo_sample.cfg zoo.cfg
vim zoo.cfg
##内容:
#修改数据存储路径配置
dataDir=/app/zookeeper-3.5.7/zkData
#增加如下配置
#######################cluster##########################
server.1=h1:2888:3888
server.2=h2:2888:3888
server.3=h3:2888:3888
##
#6、分发安装包
cd /app
scp -r zookeeper-3.5.7/ h2:$PWD
scp -r zookeeper-3.5.7/ h3:$PWD
在h2修改myid
vim /app/zookeeper-3.5.7/zkData/myid
##内容:
2
##
在h3修改myid
vim /app/zookeeper-3.5.7/zkData/myid
##内容:
3
##
3.3 启停
#三台执行启动:
cd /app/zookeeper-3.5.7
#启动
bin/zkServer.sh start
#查看状态
bin/zkServer.sh status
#停止
bin/zkServer.sh stop
4. 端口号
端口号 | 功能 |
---|---|
2181 | 客户端连接端口 |
2888 | 集群内机器通讯使用,Leader监听此端口 |
3888 | 选举leader使用 |
默认端口号,也可修改
三、数据模型
zk当中每一个节点都称之为一个 znode,每个 znode 既具有文件夹的特性,又具有文件的特性,大小不要超过 1M(临时节点不能有子节点),每个 znode 都有唯一路径表示
znode组成:
名称 | 含义 |
---|---|
czxid | 创建节点的事务 zxid,,事务 id 是 zk 中所有修改总的次序,每次修改都有唯一的 zxid,如果 zxid1 小于 zxid2,那么 zxid1 在 zxid2 之前发生 |
ctime | znode 被创建的毫秒数(从 1970 年开始) |
mzxid | znode 最后更新的事务 zxid |
mtime | znode 最后修改的毫秒数(从 1970 年开始) |
pZxid | znode 最后更新的子节点 zxid |
cversion | znode 子节点变化号,znode 子节点修改次数 |
dataversion | znode 数据变化号 |
aclVersion | znode 访问控制列表的变化号 |
ephemeralOwner | 如果是临时节点,这个是 znode 拥有者的 session id,如果不是临时节点则是 0 |
dataLength | znode 的数据长度 |
numChildren | znode 子节点数量 |
四、Shell操作
1. 客户端连接
cd $ZOOKEEPER_HOME/
#运行客户端
bin/zkCli.sh
help
2. 创建节点
#命令格式:
#-s 或 -e 分别指定节点特性、顺序或临时节点,若不指定,则表示持久节点。acl用来进行权限控制,创建节点只有绝对路径,不能使用相对路径创建
create [-s] [-e] path data acl
#创建永久节点
create /ttt twy
#创建永久顺序节点:
create -s /ttt2 twy
#创建临时节点:
create -e /ttt3 twy
#创建临时顺序节点
create -e -s /ttt4 twy
#节点下面创建节点
create /ttt/www haha
create /ttt/yyy xixi
3. 读取节点
# ls:命令可以列出ZooKeeper指定节点下的所有子节点,只能查看指定节点下的第一级的所有子节点
ls /ttt
# get:命令可以获取ZooKeeper指定节点的数据内容和属性信息
get /ttt
读取详细:
4. 更新节点
# set path data [version]
# data就是要更新的新内容,version表示数据版本
set /ttt/www wuwuwu
5. 删除节点
#方式1:不存在子节点 delete path data [version]
delete /ttt/www
#方式二:存在子节点,递归删除
# 旧版:rmr path
# 最新:deleteall path
rmr /ttt
五、JavaAPI
1. 依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.7</version>
</dependency>
</dependencies>
2. 代码
package com.twy;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.util.List;
/**
* @ClassName zkCliTest
* @Description TODO zk JavaAPI 测试
* @Author twy
* @Date 2024-03-27 17:31
* @Version 1.0
**/
public class zkCliTest {
private final String connectString = "h1:2181,h2:2181,h3:2181";
private final Integer sessionTimeout = 2000;
ZooKeeper zkCli;
@Before
public void init() throws IOException {
zkCli = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
}
});
}
/**
* TODO 创建节点
*
* @param
* @return void
* @Date 2024-03-27 17:36
**/
@Test
public void create() throws InterruptedException, KeeperException {
//create(绝对路径,数据值,权限,节点类型)
String nodeCreated = zkCli.create("/t1", "twy1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
/**
* TODO 判断节点是否存在
*
* @param
* @return void
* @Date 2024-03-27 17:42
**/
@Test
public void exist() throws KeeperException, InterruptedException {
Stat stat = zkCli.exists("/t1", false);
System.out.println(stat == null ? "not exist " : "is exist");
}
/**
* TODO 读取节点
*
* @param
* @return void
* @Date 2024-03-27 17:40
**/
@Test
public void getChildren() throws InterruptedException, KeeperException {
//getChildren(目录,是否需要监听器)
List<String> children = zkCli.getChildren("/", true);
for (String child : children) {
System.out.println(child);
}
//设置延迟
Thread.sleep(Long.MAX_VALUE);
}
}
六、watch机制
待学