Zookeeper(一)之基本概念及操作

Zookeeper(一)之基本概念及操作

引言

场景需求

在这里插入图片描述

简介

Apache ZooKeeper是Apache软件基金会的一个软件项目,它为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册。

简言:Zookeeper就是一个管理多个服务的集群管理者+文件系统

核心解决问题:

  1. 同步集群的配置信息(文件系统)
  2. 监听服务器的上下线,同时可以做出反应。(监听器)

特点

  1. 1主(Leader)多从(Follower),一旦故障就能立刻选出新的主机,继续提供服务。 自身稳定性No单点故障
  2. 集群中只要有半数以上zk节点存活,zk集群就能正常使用。 服务节点可靠性
  3. 选主和操作,使用投票机制服务的高效性、可靠性、操作的可靠性
  4. 任何一台zk主机添加的数据,都会同步到所有zk主机。 全局数据同步
  5. 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

  • 初始化配置

    1. 在zookeeper下创建data文件夹

    2. 在conf目录下通过拷贝的方式创建zoo.cfg文件

    3. 配置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

    1. 启动

    zkServer.sh start

    1. 查看状态

    zkServer.sh status

    1. 停止

    zkServer.sh stop

    1. 客户端

    zkCli.sh 登录本机的zk

    zkCli.sh -server ip:2181 登录指定ip的zk主机

文件系统

Zookeeper维护一个类似文件系统的数据结构

  1. 每个节点就是一个文件
  2. 每个节点都有一个名字一个值。
  3. 每个节点即可以是文件又可以是文件夹,下面可以继续挂节点。

在这里插入图片描述

# 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命名服务案例

在这里插入图片描述

监听通知

  1. 监听节点值的修改(set)和删除(delete)变化
  2. 监听某个节点及其子节点的增加、删除
命令 含义
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台的稳定性。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44191814/article/details/121249817
今日推荐