【Hadoop大数据技术】——ZooKeeper分布式协调服务(学习笔记)

📖 前言:ZooKeeper是一个开源的分布式协调服务,它是Google Chubby的开源实现,其设计目标是将那些复杂且容易出错的分布式应用封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用。

在这里插入图片描述


目录

  • 🕒 1. ZooKeeper简介
  • 🕒 2. ZooKeeper数据模型
  • 🕒 3. ZooKeeper的Watcher机制
  • 🕒 4. ZooKeeper的选举机制
    • 🕘 4.1 全新集群选举
    • 🕘 4.2 非全新集群选举
  • 🕒 5. ZooKeeper分布式集群部署(伪分布式)
    • 🕘 5.1 Zookeeper的安装
    • 🕘 5.2 Zookeeper的配置
    • 🕘 5.3 启动Zookeeper
  • 🕒 6. ZooKeeper的Shell操作
    • 🕘 6.1 帮助手册
    • 🕘 6.2 查看当前节点数据
    • 🕘 6.3 查看当前Zookeeper中所包含的内容
    • 🕘 6.4 创建节点
    • 🕘 6.5 获取节点
    • 🕘 6.6 修改节点
    • 🕘 6.7 监听节点
    • 🕘 6.8 删除节点
  • 🕒 7. ZooKeeper的Java API操作
    • 🕘 7.1 在Eclipse中搭建ZooKeeper环境
    • 🕘 7.2 创建会话
    • 🕘 7.3 创建ZNode
    • 🕘 7.4 判断ZNode是否存在
    • 🕘 7.5 获取ZNode的数据内容
    • 🕘 7.6 修改ZNode的数据内容
    • 🕘 7.7 查看ZNode的子节点列表
    • 🕘 7.8 删除ZNode
  • 🕒 8. ZooKeeper典型应用场景
    • 🕘 8.1 数据发布/订阅
    • 🕘 8.2 命名服务
    • 🕘 8.3 分布式锁
  • 🕒 9. 课后习题

🕒 1. ZooKeeper简介

Zookeeper主要用来解决分布式集群中应用系统的一致性问题单点故障问题,例如如何避免同时操作同一数据造成脏读的一致性问题等。

Zookeeper具有全局数据一致性、可靠性、顺序性、原子性以及实时性,可以说Zookeeper的其他特性都是为满足Zookeeper全局数据一致性这一特性。

Zookeeper集群是一个主从集群,它一般是由一个Leader(领导者)和多个Follower(跟随者)组成。此外,针对访问量比较大的Zookeeper集群,还可新增Observer(观察者)。Zookeeper集群中的三种角色各司其职,共同完成分布式协调服务。

在这里插入图片描述

  • Leader是Zookeeper集群工作的核心,也是事务性请求(写操作)的唯一调度和处理者,保证集群事务处理的顺序性,同时负责进行投票的发起和决议,以及更新系统状态。
  • Follower负责处理客户端的非事务(读操作)请求,如果接收到客户端发来的事务性请求,则会转发给Leader,让Leader进行处理,同时还负责在Leader选举过程中参与投票
  • Observer负责观察Zookeeper集群的最新状态的变化,并且将这些状态进行同步。对于非事务性请求可进行独立处理;对于事务性请求,则会转发给Leader服务器进行处理。它不参与任何形式的投票,只提供非事务性的服务

🕒 2. ZooKeeper数据模型

ZooKeeper的视图结构和标准的Unix文件系统非常类似,但没有引入Unix文件系统中目录和文件的相关概念,而是使用了其特有的“数据节点”概念,称之为ZNode。ZNode是ZooKeeper中数据的最小单元,每个ZNode默认能够保存1MB的数据,同时还可以挂载子节点,挂载的子节点也可以单独看作是ZNode,从而构成了一个层次化的命名空间,我们称之为

ZooKeeper的数据模型多个ZNode组成,如“/”“/app1”“/app2”,每个ZNode都可以挂载子节点。每个Znode都是由三部分组成,分别是statdatachildren

在这里插入图片描述
在ZooKeeper中,每个ZNode都是有生命周期的,其生命周期的长短取决于ZNode的类型。在ZooKeeper中,ZNode的类型主要分为永久节点/持久节点(PERSISTENT)、临时节点(EPHEMERAL)和顺序节点(SEQUENTIAL)

  • 永久节点:永久节点是ZooKeeper中最常见的一种ZNode类型,它的生命周期取决于用户何时进行删除操作,永久节点被创建后,便会一直存在于ZooKeeper中,除非主动删除永久节点。
  • 临时节点:与永久节点有所不同,临时节点的生命周期取决于客户端会话。所谓客户端会话是指,客户端与ZooKeeper成功建立连接后所创建的会话,若此时在ZooKeeper中创建临时节点,则客户端与ZooKeeper断开连接时,临时节点便会被自动清理掉。需要注意的是,临时节点不能挂载子节点,只能存储数据。
  • 顺序节点:顺序节点基于永久节点和临时节点所创建,可以将顺序节点分为永久顺序节点和临时顺序节点这两种类型。在创建顺序节点时,默认会在顺序节点的基础上添加一个不断增加的序号,该序号对于当前顺序节点的父节点来说是唯一的,这样便于记录父节点中每个子节点创建的先后顺序。
    序号的格式由10位数字组成,起始序号为0000000000,例如在名称为“/node”的ZNode下先后创建了3个顺序节点,那么这3个顺序节点的序号分别是“0000000000”“000000001”和“0000000002”。

Znode的类型在创建时被指定,一旦创建就无法改变。

Zookeeper中的每个Znode都包含了一系列的属性,具体属性如下所示。

属性名称相关说明属性名称相关说明
czxid节点被创建的时间dataVersion数据版本号
ctime节点最后一次的修改的Zxid值aclVersionACL版本号
mzxid节点最后一次的修改时间ephemeralOwner如果此节点为临时节点,那么该值代表这个节点拥有者的会话ID;否则值为0
mtime与该节点的子节点最后一次修改的Zxid值dataLength节点数据域长度
pZxid子节点被修改的版本号numChildren节点拥有的子节点个数
cversion节点被创建的时间

🕒 3. ZooKeeper的Watcher机制

在ZooKeeper中,引入了Watch机制来实现这种分布式的通知功能。ZooKeeper允许客户端向服务端注册一个Watch监听,当服务端的一些事件触发了这个Watch,那么就会向指定客户端发送一个事件通知,来实现分布式的通知功能。

Watch机制的特点一次性触发、事件封装、异步发送、先注册再触发

同一个事件类型在不同的连接状态中代表的含义有所不同。
常见的连接状态和事件类型如下所示。

连接状态状态含义事件类型事件含义
Disconnected连接失败NodeCreated节点被创建
SyncConnected连接成功NodeDataChanged节点数据变更
AuthFailed认证失败NodeChildrentChanged子节点数据变更
Expired会话过期NodeDeleted节点被删除

🕒 4. ZooKeeper的选举机制

Zookeeper为了保证各节点的协同工作,在工作时需要一个Leader角色,而Zookeeper默认采用FastLeaderElection算法,且投票数大于半数则胜出的机制。

  • 选举ID:选举过程中,Zookeeper服务器有四种状态,分别为竞选状态、随从状态、观察状态、领导者状态。
  • 数据ID:是服务器中存放的最新数据版本号,该值越大则说明数据越新,在选举过程中数据越新权重越大。
  • 服务器ID:设置集群myid参数时,参数分别为服务器1、服务器2、服务器3,编号越大FastLeaderElection算法中权重越大。
  • 逻辑时钟;逻辑时钟被称为投票次数,同一轮投票过程中逻辑时钟值相同,逻辑时钟起始值为0,每投一次票,数据增加。与接收到其它服务器返回的投票信息中数值比较,根据不同值做出不同判断。

Zookeeper选举机制有两种类型,分别为全新集群选举和非全新集群选举。全新集群选举是新搭建起来的,没有数据ID和逻辑时钟的数据影响集群的选举;非全新集群选举时是优中选优,保证Leader是Zookeeper集群中数据最完整、最可靠的一台服务器。

🕘 4.1 全新集群选举

假设有5台编号分别是1~5的服务器,全新集群选举过程如下:

  1. 服务器1启动,先给自己投票;其次,发投票信息,由于其它机器还没有启动所以它无法接收到投票的反馈信息,因此服务器1的状态一直属于竞选状态。
  2. 服务器2启动,先给自己投票;其次,在集群中启动Zookeeper服务的机器发起投票对比,它会与服务器1交换结果,由于服务器2编号大,服务器2胜出,服务器1会将票投给服务器2,此时服务器2的投票数并没有大于集群半数,两个服务器状态依旧是竞选状态。
  3. 服务器3启动,先给自己投票;其次,与之前启动的服务器1、2交换信息,服务器3的编号最大,服务器3胜出,服务器1、2会将票投给服务器3,此时投票数正好大于半数,所以服务器3成为领导者状态,服务器1、2成为追随者状态。
  4. 服务器4启动,先给自己投票;其次,与之前启动的服务器1、2、3交换信息,尽管服务器4的编号大,但是服务器3已经胜,所以服务器4只能成为追随者状态。
  5. 服务器5启动,同服务器4一样,均成为追随者状态。

🕘 4.2 非全新集群选举

  1. 统计逻辑时钟是否相同,逻辑时钟小,则说明途中可能存在宕机问题,因此数据不完整,那么该选举结果被忽略,重新投票选举。
  2. 统一逻辑时钟后,对比数据ID值,数据ID反应数据的新旧程度,因此数据ID大的胜出。
  3. 如果逻辑时钟和数据ID都相同的情况下,那么比较服务器ID(编号),值大则胜出。

🕒 5. ZooKeeper分布式集群部署(伪分布式)

Zookeeper集群搭建通常是由2n+1台服务器组成,这是为了保证 Leader 选举(基于Paxos算法的实现)能够通过半数以上台服务器选举支持,因此,ZooKeeper集群的数量一般为奇数台。

🕘 5.1 Zookeeper的安装

在Ubuntu下打开官网:🔎 ZooKeeper官网 进行下载

在这里插入图片描述

选择最新版下载即可

在这里插入图片描述

下载完成后,打开终端,解压安装包apache-zookeeper-3.9.2-bin.tar.gz至路径 /opt,命令如下:

sudo tar -zxvf apache-zookeeper-3.9.2-bin.tar.gz -C /opt

将解压的文件夹重命名为zookeeper并添加zookeeper的权限

sudo mv apache-zookeeper-3.9.2-bin/ zookeeper # 更名为zookeeper
sudo chown -R hadoop:hadoop zookeeper # 把zookeeper文件夹的权限赋给hadoop用户和hadoop组。

🕘 5.2 Zookeeper的配置

为模拟3个分布式节点,所以须要创建三个节点的配置文件 zoo1.cfg、zoo2.cfg、zoo3.cfg

cd /opt/zookeeper/conf/

将zoo_sample.cfg改名为zoo1.cfg

sudo mv zoo_sample.cfg zoo1.cfg
cp zoo1.cfg zoo2.cfg
cp zoo1.cfg zoo3.cfg

在这里插入图片描述

zoo1.cfg配置如下 (注意以下标红的地方)

sudo vim zoo1.cfg
dataDir=/opt/zookeeper/data/zk1	# 设置数据持久化目录
# 设置客户端连接当前ZooKeeper服务使用的端口号
clientPort=2181
# 设置ZooKeeper集群中每个ZooKeeper服务的地址及端口号
server.1=ubuntu:2888:3888
server.2=ubuntu:2889:3889
server.3=ubuntu:2890:3890

在这里插入图片描述

zoo2.cfgzoo3.cfg修改方式同理,配置如下

dataDir=/opt/zookeeper/data/zk2	
clientPort=2182
server.1=ubuntu:2888:3888
server.2=ubuntu:2889:3889
server.3=ubuntu:2890:3890
dataDir=/opt/zookeeper/data/zk3	
clientPort=2183
server.1=ubuntu:2888:3888
server.2=ubuntu:2889:3889
server.3=ubuntu:2890:3890

配置说明:

  • tickTime:这个时间是作为 Zookeeper server之间或client与server之间维持心跳的时间间隔,也就是每一个 tickTime 时间就会发送一个心跳。
  • initLimit:这个配置项是用来配置 Zookeeper 接受client(这里所说的client不是用户连接 Zookeeper server的client,而是 Zookeeper server集群中连接到 Leader 的 Follower server)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 10个心跳的时间(也就是 tickTime)长度后 Zookeeper server还没有收到client的返回信息,那么表明这个client连接失败。
  • syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息。请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度。
  • dataDir:Zookeeper 保存数据的文件夹,默认情况下,Zookeeper 将写数据的日志文件也保存在这个文件夹里。
  • clientPort:这个port就是client连接 Zookeeper server的port。Zookeeper 会监听这个port,接受client的访问请求。
  • server.A=B:C:D:当中 A 是一个数字。表示这个是第几号server;B 是这个server的 ip 地址;C 表示的是这个server与集群中的 Leader server交换信息的port;D 表示的是万一集群中的 Leader server挂了。须要一个port来又一次进行选举。选出一个新的 Leader。而这个port就是用来运行选举时server相互通信的port。假设是伪集群的配置方式,因为 B 都是一样,所以不同的 Zookeeper 实例通信port号不能一样,所以要给它们分配不同的port号。

创建zookeeper保存数据文件:

sudo mkdir -p /opt/zookeeper/data/zk1
sudo mkdir -p /opt/zookeeper/data/zk2
sudo mkdir -p /opt/zookeeper/data/zk3

创建节点标识:

在下面三个文件夹下分别创建myid文件
里面分别写1、2、3用于标识第几号server

cd /opt/zookeeper/data/zk1
sudo echo 1>myid
cd /opt/zookeeper/data/zk2
sudo echo 2>myid
cd /opt/zookeeper/data/zk3
sudo echo 3>myid

🕘 5.3 启动Zookeeper

cd /opt/zookeeper/
sudo chmod -R 777 data/
./bin/zkServer.sh start conf/zoo1.cfg
./bin/zkServer.sh start conf/zoo2.cfg
./bin/zkServer.sh start conf/zoo3.cfg

查看启动状态:

./bin/zkServer.sh status conf/zoo1.cfg
./bin/zkServer.sh status conf/zoo2.cfg
./bin/zkServer.sh status conf/zoo3.cfg

运行截图:
在这里插入图片描述在这里插入图片描述

验证zookeeper安装的正确性:

./bin/zkCli.sh -server 127.0.0.1:2182

在这里插入图片描述

如果连接成功,会有Welcome to zookeeper!和state状态等信息。证明已经成功连接到zookeeper服务。

停止server的命令:

./bin/zkServer.sh stop conf/zoo1.cfg
./bin/zkServer.sh stop conf/zoo2.cfg
./bin/zkServer.sh stop conf/zoo3.cfg

🕒 6. ZooKeeper的Shell操作

🕘 6.1 帮助手册

[zk: 127.0.0.1:2182(CONNECTED) 0] help
ZooKeeper -server host:port -client-configuration properties-file cmd args
	addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE
	addauth scheme auth
	close 
	config [-c] [-w] [-s]
	connect host:port
	create [-s] [-e] [-c] [-t ttl] path [data] [acl]
	delete [-v version] path
	deleteall path [-b batch size]
	delquota [-n|-b|-N|-B] path
	get [-s] [-w] path
	getAcl [-s] path
	getAllChildrenNumber path
	getEphemerals path
	history 
	listquota path
	ls [-s] [-w] [-R] path
	printwatches on|off
	quit 
	reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
	redo cmdno
	removewatches path [-c|-d|-a] [-l]
	set [-s] [-v version] path data
	setAcl [-s] [-v version] [-R] path acl
	setquota -n|-b|-N|-B val path
	stat [-w] path
	sync path
	version 
	whoami 
Command not found: Command not found help
[zk: 127.0.0.1:2182(CONNECTED) 1] 

🕘 6.2 查看当前节点数据

在这里插入图片描述

🕘 6.3 查看当前Zookeeper中所包含的内容

在这里插入图片描述

🕘 6.4 创建节点

创建节点命令格式:create [-s] [-e] [-c] [-t ttl] path [data] [acl]

  • -s:指定ZNode的类型为顺序节点。
  • -e:指定ZNode的类型为临时节点,若不指定,则表示永久节点。
  • path:表示创建的路径
  • data:表示创建节点的数据,这是因为Znode可以像目录一样存在也可以像文件一样保存数据。
  • Acl:进行权限控制。一般不需要了解。

示例:创建临时节点
在这里插入图片描述

🕘 6.5 获取节点

获取节点命令格式:get [-s] [-w] path

  • -s:查看指定ZNode的属性。
  • -w:向指定ZNode注册Watcher。

获取Zookeeper指定节点的数据内容以及属性信息:

在这里插入图片描述

🕘 6.6 修改节点

修改节点命令格式:set [-s] [-v version] path data

  • data:表示要修改的内容,该数据内容不允许出现空格。
  • version:表示数据版本

对前面创建的临时节点testnode-temp进行修改,使得节点内容变成“123”的操作:

在这里插入图片描述

🕘 6.7 监听节点

监听节点就是监听节点变化,概括为三个过程。客户端向服务端注册Watch、服务端事件发生触发Watch、客户端回调Watch得到触发事件的情况。

在这里插入图片描述

🕘 6.8 删除节点

删除节点命令格式:delete [-v version] path

使用delete命令删除节点时,若要删除的节点存在子节点,就无法删除该节点,必须先删除子节点,才可删除父节点。使用rmr命令递归删除节点,不论该节点下是否存在子节点,可以直接删除。

在这里插入图片描述

🕒 7. ZooKeeper的Java API操作

Zookeeper API包含五个包:

org.apache.zookeeper
org.apache.zookeeper.data
org.apache.zookeeper.server
org.apache.zookeeper.server.quorum
org.apache.zookeeper.server.upgrade

org.apache.zookeeper包含Zookeeper类,这也是编程时最常用的类文件,Zookeeper类提供的常用Java API方法。

方法名称方法描述
create创建节点
delete删除节点
exists判断节点是否存在
get/setData获取/修改节点数据
getChildren获取指定节点下的所有子节点列表

🕘 7.1 在Eclipse中搭建ZooKeeper环境

新建Java项目,取名ZooKeeperDemo,之后Next,添加依赖

在这里插入图片描述

导入全部依赖,之后新建类ZKTest,开始写代码

🕘 7.2 创建会话

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class ZKTest {
	public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        getConnect();
        
	}
	
	// 连接ZooKeeper服务
	public static ZooKeeper getConnect()
            throws IOException,InterruptedException {
        String zkServer = "Ubuntu:2181";		// 此处Ubuntu改成自己的主机名
        CountDownLatch countDownLatch = new CountDownLatch(1);
        ZooKeeper zooKeeper = new ZooKeeper(zkServer, 3000, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                System.out.println("通知状态:"+watchedEvent.getState() + "\t"
                        + "事件类型:" + watchedEvent.getType() + "\t"
                        + "节点路径:" + watchedEvent.getPath());
                if (Event.KeeperState.SyncConnected == watchedEvent.getState()){
                    countDownLatch.countDown();
                }
            }
        });
        countDownLatch.await();
        return zooKeeper;
    }
}

在这里插入图片描述
如图所示即成功连接。

🕘 7.3 创建ZNode

创建持久节点zkapi,并且在持久节点zkapi中挂载子节点zkChild,该子节点的ZNode类型为持久节点,createNode()方法的代码如下。

public class ZKTest {
	public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        createNode();
	}
	
	// 使用create方法创建ZNode
    public static void createNode()
            throws IOException, InterruptedException, KeeperException {
        ZooKeeper connect = getConnect();
        connect.create(
                "/zkapi",
                "fruit".getBytes(),
                ZooDefs.Ids.OPEN_ACL_UNSAFE,
                CreateMode.PERSISTENT);
        connect.create(
                "/zkapi/zkChild",
                "apple".getBytes(),
                ZooDefs.Ids.OPEN_ACL_UNSAFE,
                CreateMode.PERSISTENT);
    }
}

在这里插入图片描述

🕘 7.4 判断ZNode是否存在

判断永久节点zkapi是否存在,existsNode()方法的代码如下所示。

public class ZKTest {
	public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
	    Stat stat = existsNode();
        if (stat != null){
            System.out.println("已存在");
        }else {
            System.out.println("不存在");
        }
	}
	
	// 使用exists方法判断ZNode是否存在
	public static Stat existsNode()	 
			throws IOException, InterruptedException, KeeperException {
		ZooKeeper connect = getConnect();
		Stat exists = connect.exists("/zkapi", true);
		return exists;
	}
}

在这里插入图片描述

🕘 7.5 获取ZNode的数据内容

获取永久节点zkapi的数据内容,getNode()方法的代码如下所示。

public class ZKTest {
	public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
	    byte[] nodeData = getNode();
        System.out.println("持久节点zkapi的数据内容为:"+new String(nodeData));
	}
	
	// 使用getData方法获取ZNode的数据内容
	public static byte[] getNode() 
			 throws IOException, InterruptedException, KeeperException {
		 ZooKeeper connect = getConnect();
		 byte[] data = connect.getData("/zkapi", true, null);
		 return data;
	}
}

在这里插入图片描述

🕘 7.6 修改ZNode的数据内容

将持久节点zkapi的数据内容修改为fruit_new,updateNode()方法的代码如下。

public class ZKTest {
	public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        Stat beforeStat = existsNode();
        System.out.println("持久节点zkapi修改数据内容前的数据版本号:"
                +beforeStat.getVersion());
        System.out.println("持久节点zkapi修改数据内容前的数据内容长度:"
                +beforeStat.getDataLength());
        byte[] beforeNode = getNode();
        System.out.println("持久节点zkapi修改数据内容前的数据内容:"
                +new String(beforeNode));
        Stat afterStat = updateNode();
        System.out.println("持久节点zkapi修改数据内容后的数据版本号:"
                +afterStat.getVersion());
        System.out.println("持久节点zkapi修改数据内容后的数据内容长度:"
                +afterStat.getDataLength());
        byte[] afterNode = getNode();
        System.out.println("持久节点zkapi修改数据内容后的数据内容:"
                +new String(afterNode));
	
	}
	
	// 使用setData方法修改ZNode的数据内容
	public static Stat updateNode()
			throws IOException, InterruptedException, KeeperException {
		ZooKeeper connect = getConnect();
		Stat stat = connect.setData(
		      "/zkapi",
		      "fruit_new".getBytes(),
		      -1);
		return stat;
	}
}

在这里插入图片描述

🕘 7.7 查看ZNode的子节点列表

查看持久节点zkapi的子节点列表,getChildNode()方法的代码如下。

public class ZKTest {
	public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        List<String> childNodes = getChildNode();
        for (String childNode : childNodes) {
            System.out.println("持久节点zkapi的子节点:"+childNode);
        }
	
	}
	
	// 使用getChildren方法查看ZNode的子节点列表
	public static List<String> getChildNode()
			  throws IOException, InterruptedException, KeeperException {
		  ZooKeeper connect = getConnect();
		  List<String> nodeList = connect.getChildren("/zkapi", false);
		  return nodeList;
	}
}

在这里插入图片描述

🕘 7.8 删除ZNode

该方法用于删除持久节点zkapi的子节点zkChild,deleteNode()方法的代码如下。

public class ZKTest {
	public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
        deleteNode();
	    List<String> childNodes = getChildNode();
	    for (String childNode : childNodes) {
	        System.out.println("持久节点zkapi的子节点:"+childNode);
	    }
	
	}
	
	// 使用delete方法删除ZNode
	public static void deleteNode()
			 throws IOException, InterruptedException, KeeperException {
	      ZooKeeper connect = getConnect();
	      connect.delete("/zkapi/zkChild",-1);
	}
}

在这里插入图片描述

🕒 8. ZooKeeper典型应用场景

🕘 8.1 数据发布/订阅

数据发布/订阅,顾名思义就是发布者将数据发布到ZooKeeper的一个或一系列ZNode上,供订阅者进行数据订阅,达到动态获取数据的目的,实现配置信息的集中式管理和数据的动态更新。
在数据发布/订阅中应用ZooKeeper时,订阅者会向ZooKeeper指定的ZNode注册一个Watcher进行监听,一旦该ZNode的数据发生变化,那么ZooKeeper就会向相应的订阅者发送事件通知,当订阅者接收到这个通知后,便会主动到ZooKeeper指定的Znode中获取最新的数据。

🕘 8.2 命名服务

命名服务也是分布式系统中比较常见的一类应用场景,它是分布式应用最基础的公共服务之一。在分布式应用中,被命名的实体通常可以是集群中的服务器、提供服务的地址或远程对象等,这些实体我们都可以统称为命名空间(NameSpace),其中较为常见的就是一些分布式服务框架(如RPC、RMI)中的服务地址列表,通过命名服务,客户端能够根据指定名字从ZooKeeper来获取资源的实体、服务地址和提供者等信息。

🕘 8.3 分布式锁

分布式锁是控制分布式应用之间同步访问共享资源的一种方式。如果不同的应用或是同一应用的不同主机之间共享资源,那么访问这些资源的时候,往往需要通过一些互斥手段来防止彼此之间的干扰,以保证一致性,在这种情况下,就需要使用分布式锁。分布式锁的类型主要分为排他锁和共享锁。

🕒 9. 课后习题

选择题
1、Zookeeper启动时会最多监听几个端口()
A、1
B、2
C、3
D、4

2、下列关于zookeeper描述正确的是:()
A、无论客户端连接的是哪个Zookeeper服务器,其看到的服务端数据模型都是一致的
B、从同一个客户端发起的事务请求,最终将会严格按照其发起顺序被应用到zookeeper中
C、在一个5个节点组成的Zookeeper集群中,如果同时有3台机器宕机,服务不受影响
D、如果客户端连接到Zookeeper集群中的那台机器突然宕机,客户端会自动切换连接到集群其他机器

答案:1.B(集群运行:一个是提供服务的端口,供客户端连接
一个是集群时leader选举的端口,在选举leader时,使用这个端口进行相互通讯) 2.A(B是不同客户端、C是服务失效、D是不会自动切换)

判断题
1、Zookeeper对节点的Watch监听通知是永久性的。
2、Zookeeper集群宕机数超过集群数一半,则Zookeeper服务失效。
3、Zookeeper可以作为文件存储系统,因此可以将大规模数据文件存在该系统中。

答案:1.×(每次客户端连接服务器时会触发一次,然后清除) 2.√(高可用“半数容错”) 3.×(大小有限制,适合小规模)


OK,以上就是本期知识点“ZooKeeper分布式协调服务”的知识啦~~ ,感谢友友们的阅读。后续还会继续更新,欢迎持续关注哟📌~
💫如果有错误❌,欢迎批评指正呀👀~让我们一起相互进步🚀
🎉如果觉得收获满满,可以点点赞👍支持一下哟~

❗ 转载请注明出处
作者:HinsCoder
博客链接:🔎 作者博客主页

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/476489.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C# 右键快捷菜单(上下文菜单)的两种实现方式

在C#中&#xff0c;ContextMenuStrip是一种用于创建右键菜单的控件。它提供了一种方便的方式来为特定的控件或窗体添加自定义的上下文菜单选项。有两种实现方式&#xff0c;如下&#xff1a; 一.通过ContextMenuStrip控件实现 1.从工具箱中拖一个ContextMenuStrip控件到窗体上…

尝试搭建谷粒商城 记录(四)

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。 本文链接&#xff1a;https://blog.csdn.net/weixin_44190665/article/details/121043585 ———————————————— 版权声明&#xff1…

爬虫工作量由小到大的思维转变---<第四十九章 Scrapy 降维挖掘---中间件系列(1)>

前言&#xff1a; Scrapy是一个功能强大的网络爬虫框架&#xff0c;但在实际应用过程中&#xff0c;中间件问题可能会成为一个令人头痛的难题。为了彻底解决Scrapy中的各种疑难杂症&#xff0c;我决定进行第四次全面的学习和实践&#xff0c;并将中间件的问题一一拆解&#xff…

【DL经典回顾】激活函数大汇总(四十二)(CosReLU附代码和详细公式)

激活函数大汇总(四十二)(CosReLU附代码和详细公式) 更多激活函数见激活函数大汇总列表 一、引言 欢迎来到我们深入探索神经网络核心组成部分——激活函数的系列博客。在人工智能的世界里,激活函数扮演着不可或缺的角色,它们决定着神经元的输出,并且影响着网络的学习能…

幸运数字(第十四届蓝桥杯JavaB组省赛真题)

进制转换可以参考如下的十进制&#xff0c;基本一样的&#xff0c;只是把10变成了其他数字&#xff0c; sum就是各个数位之和 public static int myUtil(int n) {int sum 0;while(n > 0) {sum n % 10;n / 10;}return sum;} 注意&#xff1a; 如果写在同一个类里面&…

@arco.design radioGroup 组件手写 beforeChange 方法

官方是没有提供 beforeChange 事件的&#xff0c;只能自己写一个 子组件&#xff08;CustomRadioGroup&#xff09; <template><a-radio-group :model-value"modelValue" change"onRadioChange"><a-radio v-for"item in list" …

面试算法-72-删除排序链表中的重复元素

题目 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2] 解 class Solution {public ListNode deleteDuplicates(ListNo…

鸿蒙一次开发,多端部署(八)典型布局场景

虽然不同应用的页面千变万化&#xff0c;但对其进行拆分和分析&#xff0c;页面中的很多布局场景是相似的。本小节将介绍如何借助自适应布局、响应式布局以及常见的容器类组件&#xff0c;实现应用中的典型布局场景。 说明&#xff1a; 在本文 媒体查询 小节中已经介绍了如何通…

按键模拟精灵

按键模拟精灵功能简单&#xff1a; 1.添加模拟按键 2.删除模拟按键 3.开始模拟 4.停止模拟 适合简单的按键操作&#xff0c;有需要的可以点赞收藏关注我&#xff01;

Linux学习之自定义协议

前言&#xff1a; 首先对于Tcp的socket的通信&#xff0c;我们已经大概了解了&#xff0c;但是其中其实是由一个小问题&#xff0c;我们目前是不得而知得&#xff0c;在我们客户端与服务端连接成功后&#xff0c;服务端读取来自客户端得消息&#xff0c;我们使用的是函数read,…

电子科技大学链时代工作室招新题C语言部分---题号H

1. 题目 最有操作的一道题&#xff0c;有利于对贪心算法有个初步了解。 这道题的开篇向我们介绍了一个叫汉明距离的概念。 汉明距离指的就是两个相同长度的字符串的不同字符的个数。 例如&#xff0c;abc和acd&#xff0c;b与c不同&#xff0c;c与d不同&#xff0c;所以这两个…

【Leetcode每日一题】 递归 - Pow(x, n)(难度⭐⭐)(40)

1. 题目解析 题目链接&#xff1a;50. Pow(x, n) 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 在这个算法中&#xff0c;递归函数的任务是求出 x 的 n 次方。那么&#xff0c;这个函数是怎么工作的呢&#xff1f;它…

基于springboot的大学生租房平台系统

技术&#xff1a;springbootmysqlvue 一、系统背景 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对大学生租房信息管理混乱…

RocketMQ学习笔记四(黑马)项目

课程地址&#xff1a; 1.Rocket第二章内容介绍_哔哩哔哩_bilibili &#xff08;视频35~88&#xff0c;搭建了一个电商项目&#xff0c;8h&#xff09; 待学&#xff0c;待完善。 项目安装&#xff08;打包&#xff09;的命令&#xff1a;&#xff08;注意-D后有空格&#xff09…

数据挖掘之关联规则

“啤酒和尿布的荣誉” 概念 项 item&#xff1a;单个的事物个体 &#xff0c;I{i1,i2…im}是所有项的集合&#xff0c;|I|m是项的总数项集&#xff08;item set)/模式&#xff08;pattern)&#xff1a;项的集合&#xff0c;包含k个项的项集称为k-项集数据集(data set)/数据库…

NCV8664CST50T3G稳压器芯片中文资料规格书PDF数据手册引脚图图片价格参数

产品概述&#xff1a; NCV8664C 是一款精确 3.3 V 和 5.0 V 固定输出&#xff0c;低漏集成式电压稳压器&#xff0c;输出电流能力为 150 mA。对轻型负载电流消耗的精心管理&#xff0c;并结合低漏工艺&#xff0c;实现了 22 A 的典型静态电流。输出电压精度在 2.0&#xff05;…

TikTok运营要用什么代理IP?如何分辨?

对于运营TikTok的从业者来说&#xff0c;IP的重要性自然不言而喻。 在其他条件都正常的情况下&#xff0c;拥有一个稳定&#xff0c;纯净的IP&#xff0c;你的视频起始播放量很可能比别人高出不少&#xff0c;而劣质的IP轻则会限流&#xff0c;重则会封号。那么&#xff0c;如何…

Linux 文件系统:重定向、缓冲区

目录 一、重定向 1、输出重定向 2、输入重定向 3、追加重定向 4、dup2 系统调用 二、理性理解Linux系统下“一切皆文件” 了解硬件接口 三、缓冲区 1、为什么要有缓冲区? 2、刷新策略 3、缓冲模式改变导致发生写时拷贝 未创建子进程时 创建子进程时 使用fflush…

贾志杰“大前端”系列著作出版发行

杰哥著作《VueSpringBoot前后端分离开发实战》2021年出版以来&#xff0c;累计发行2.6万册&#xff0c;受到广大读者热捧。后应读者要求&#xff0c;受出版社再次邀请&#xff0c;“大前端”系列之《剑指大前端全栈工程师》、《前端三剑客》由清华大学出版社陆续出版发行。系列…

Django日志(二)

一、Handler Handler决定如何处理logger中的每条消息。它表示一个特定的日志行为,例如 将消息写入屏幕、文件或网络Socket handler对应的是个字典,每一个键都是一个handler的名字,每个值又一个字典,描述了如何配置对应的handler实例 2.1、内置Handler class(必需):处理…