ZooKeeper 基础知识总结

先赞后看,Java进阶一大半

ZooKeeper 官网这样介绍道:ZooKeeper 是一种集中式服务,用于维护配置信息、命名、提供分布式同步和提供组服务。

在这里插入图片描述

各位hao,我是南哥,相信对你通关面试、拿下Offer有所帮助。

⭐⭐⭐一份南哥编写的《Java学习/进阶/面试指南》:https://github/JavaSouth

1. ZooKeeper的协议

1.1 ZAB协议

面试官:知道ZAB协议吗?

要深入学习ZooKeeper前,南哥认为我们要先学习ZooKeeper的核心理念,所有的ZooKeeper行为都是围绕这个核心来进行的。说了那么多,它就是——ZAB协议。

ZAB协议英文全称叫ZooKeeper Atomic Broadcast,我们透过中文含义可以大概了解他做了什么事情:ZooKeeper原子消息广播协议。

来看看原子广播在维基百科的解释。

在容错分布式计算中,原子广播或全序广播是指多进程系统中的所有正确进程都以相同顺序接收同一组消息(即相同的消息序列)的广播。

那ZooKeeper广播啥呢?我们知道ZooKeeper集群有Leader服务器、Follower服务器,这个Leader服务器接收了客户端所有的事务请求,事务请求可以是新增某一个ZNode节点,也可以是删除某一个ZNode节点。

这些事务请求的变更要不要提交、如何通知其他Follower服务器进行同步变更,这就是广播涉及的主要内容了。

ZAB协议主要包含了消息广播、崩溃模式,跟着南哥往下看看。

1.2 消息广播

面试官:消息广播你讲一讲?

ZAB协议的消息广播类似于二阶段提交过程。顾名思义事务最终的提交要分为两个阶段。

消息广播的流程如下:

(1)针对客户端的事务请求,Leader服务器会为其生成对应的事务Proposal,同时广播给集群中其余Followr机器。这个事务Proposal我们可以把他理解为事务提案。

(2)Follower服务器在接收到事务Proposal后会以事务日志形式写入到本地磁盘中,如果写入成功,则反馈一个Ack反馈给到Leader服务器。

(3)Leader服务器会收集其他Follower服务器的选票,只有半数的Follow服务器同意本次事务请求,那Leader服务器就会广播一个Commit消息,通知所有Follower服务器进行事务提交。

总结下来,也就是分为二个阶段,第一阶段是询问事务Proposal的写入尝试能否成功,第二阶段就是在Leader服务器、Follower服务器进行事务提交。

在这里插入图片描述

1.3 消息广播的缺点

面试官:那二阶段提交有什么缺点吗?

当然消息广播的二阶段提交有所缺点。

(1)在消息广播的第二阶段,如果有部分Follower服务器没有收到Leader服务器广播的事务提交消息,这就会出现数据不一致的情况了。

(2)单点问题。如果Leader服务器在第二阶段奔溃了,那其他Follower服务器仍然会处于锁定上一次事务资源的状态中。

(3)同步阻塞问题。参与一个客户端事务请求时,Leader、Follower服务器的其他逻辑都需要进行阻塞,直到等到上一个二阶段提交完成之后才会开始执行。

1.4. 崩溃模式

面试官:崩溃模式呢?

ZAB协议涉及Leader服务器、Follower服务器,Leader服务器充当了最重要的作用。如果Leader服务器崩溃了或者失去和Follwer服务器之间的联系,那上面南哥提到的二阶段提交各种问题很可能都会出现。

开头不是说ZAB协议包含了消息广播、崩溃模式?别慌,崩溃模式就是为此而生的。

崩溃模式总的来说就做了两个事情,我们记住这两点方便理解:一个是确保提交已经被Leader提交的事务Proposal,另一个是丢弃已经被跳过的事务Proposal。

(1)为了解决上文的第1点问题。Leader服务器会为每一个Follower服务器都准备一个Proposal消息队列,通过该队列发送那些没有被各Follower服务器同步的事务Proposal,同时在Proposal消息后面加上Commit消息让Follower服务器进行事务提交。这可以解决二阶段提交带来的数据不一致问题。

(2)为了解决上文的第2点问题。ZooKeeper设计了一个高32位的epoch,用来作为Leader服务器的标识;设计了一个低32位的事务偏移量ZXID,用来作为最新已提交事务的偏移量。

新的Leader服务器上线后,新的Leader服务器拥有集群里最大的事务偏移量,Leader服务器会和Follower服务器的ZXID进行比对,从而让Follower服务器回退被跳过的事务Proposal。

2. ZooKeeper数据模型

2.1 ZooKeeper数据节点

面试官:你说说ZooKeeper数据模型?

ZooKeeper的数据模型是一颗树结构,每一个树节点是一个数据节点,我们称它为ZNode

而每一个ZNode的节点路径标识使用斜杠/作为分隔符,我们可以在ZNode节点下写入数据、创建节点,这种斜杠/作为路径分隔符的方式和Unix文件系统路径非常相似。

大家可以看下Unix文件系统路径,以斜杠/作为路径分隔符。

# 根目录
/
# 可执行文件所在位置
/bin
# 设备驱动
/dev

这是ZooKeeper数据模型概念图,是不是非常类似呢?

在这里插入图片描述

另外ZooKepper这种斜杠/作为路径分隔符正好和Windows相反,Windows使用的是反斜杠\

# Windows路径示例
C:\Java\jdk1.8.0_311

2.2 数据节点类型

面试官:那ZooKeeper数据节点有几种类型?

ZooKeeper一共有四种节点类型,但从整体来看主要是持久节点类型、临时节点类型这两种,另外两种类型只是在以上两种节点类型基础上增加了顺序的特性。大家这样理解会更方便记忆~

  1. 持久节点:这种数据节点一旦背创建后,就会一直存在于ZooKeeper服务器上,除非对该数据节点执行删除操作。
  2. 持久顺序节点:刚刚和大家说了,该节点类型就是在持久节点基础上增加了顺序的特性。如果在持久顺序节点类型的父节点创建子节点,ZooKeeper会为该子节点名加上一个数字后缀来维护子节点的顺序。
  3. 临时节点:临时节点比较特殊,它的生命周期是和客户端会话绑定在一起的。这个客户端可以是连接ZooKeeper的某一个终端命令窗口,也可以是连接ZooKeeper的某一个Spring服务线程。如果客户端会话失效了,那这个临时节点就会被自动清除。
  4. 临时顺序节点:在临时节点的基础上添加了顺序特性。

另外大家记住一点,临时节点只能作为叶子节点,是不能在临时节点下面创建任何子节点的。原因大概是临时节点子节点没有存在的意义,创建子节点的场景大多是基于持久节点的场景,这种设计也可以防止对临时节点的误用。

2.3 数据节点的版本

面试官:数据节点版本知道吧?

ZooKeeper数据节点的版本概念和CAS操作的版本概念是一样的,同样是在多线程环境下,通过乐观锁这种无锁操作来保证线程安全性。

当一个数据节点被创建后,该节点的version值为0,代表它被更新过0次,如果后续对该节点进行更新操作,那version便会递增。

对数据节点的每次更新,都会对比数据节点的version是否是预期值,只有符合预期值,才会将新值更新到该数据节点。

大家可以通过以下CAS例子代码来了解CAS操作的执行过程。

@Slf4j
public class CAS implements Runnable {

    private static AtomicInteger val = new AtomicInteger(0);

    private void compareSwap(int expectVal, int operateVal) {
        if (val.compareAndSet(expectVal, operateVal)) {
            log.info("the thread called {} operated", Thread.currentThread().getName());
        } else {
            this.run(); // 相当于获取不到锁则重新执行
        }
    }

    @Override
    public void run() {
        int curVal = val.get();
        log.info("the thread called {} get val is {}", Thread.currentThread().getName(), curVal);
        compareSwap(curVal, curVal + 1);
    }

    public static void main(String[] args) throws InterruptedException {
        CAS cas0 = new CAS();
        CAS cas1 = new CAS();

        Thread thread0 = new Thread(cas0, "cas0");
        Thread thread1 = new Thread(cas1, "cas1");
        thread0.start();
        thread1.start();
        thread0.join();
        thread1.join();
        log.info("current thread name: {} , the value of val: {}", Thread.currentThread().getName(), val);
    }
}

控制台打印:
[ INFO ]the thread called cas0 get val is 0
[ INFO ]the thread called cas1 get val is 0
[ INFO ]the thread called cas0 operated
[ INFO ]the thread called cas1 get val is 1
[ INFO ]the thread called cas1 operated
[ INFO ]current thread name: main , the value of val: 2

2.4 事务ID

面试官:ZooKeeper事务ID呢?

我们熟悉的数据库事务一般是包含对数据库状态的读写操作,数据库事务具有ACID特性:原子性、一致性、持久性、隔离性。数据库事务这块大家有不懂的可以看我往期文章《MySQL事务的性情很“原子“,要么执行要么不执行》。

但ZooKeeper的事务和数据库事务大相径庭。ZooKeeper事务一般是包括对数据节点的创建、删除、更新,也包括客户端会话创建、失效情况对临时节点的影响。

每一个事务请求,ZooKeeper都会为其分配一个全局唯一的事务ID,我们称它为ZXID。所以ZXID也可以间接反映出对数据节点操作的全局顺序,这个全局顺序在Follower服务器对Leader服务器的数据复制上相当重要,可以用来保证数据的一致性。

2.5 Watcher机制

面试官:ZooKeeper数据变更通知使用什么对象?

ZooKeeper拥有分布式通知的功能,这个功能是基于Watcher机制来实现的。一个Watcher对象就像一个订阅者,当订阅的主题状态发生变化,就会通知Watcher订阅者作出一定动作。

Watcher机制的工作流程,首先是客户端向ZooKeeper服务器注册Watcher通知,接着会将Watcher对象存储在客户端本身的WatchManager中。当ZooKeeper服务器触发Watcher事件后会向客户端发起通知,客户端就从本身的WatchManager取出对应的Watcher对象来执行回调操作

Watcher机制的大致流程大家可以参考下图:

在这里插入图片描述

3. ZooKeeper分布式锁

3.1 排他锁实现分布式锁

面试官:知道Zookeeper有什么应用场景吗?

目前地球村里大型公司部署的分布式技术,绝大部分都是由Zookeeper提供底层的技术支持,所以Zookeeper多么重要就不用我多说了吧。

我们可以利用Zookeeper来完成分布式系统涉及的各种核心功能,例如以下4种:

  1. 数据发布/订阅。可以用来实现配置中心。

  2. 命名服务。类似于UUID,可以生成全局唯一的ID。

  3. 集群管理。每一个服务器是一个子节点,可以用来检测到集群中机器的上/下线情况。

  4. 分布式锁。

南哥先讲下我们可以怎么利用Zookeeper来实现分布式锁,要实现分布式锁,分为获取锁和释放锁两个步骤。

ZooKeepr获取锁时会在/exclusive_lock节点下创建子节点,如果创建成功则获得锁。如果创建失败,则访问Zookeeper的客户端会在该节点注册一个Watcher监听,用来实时监控子节点的变更从而重新获得锁,这有点类似于线程的循环等待。

当要释放锁时,Zookeeper会删除该子节点,此时/exclusive_lock节点下就有空位了。Watcher监听则通知客户端可以重新创建子节点来获得锁资源。

在这里插入图片描述

3.2 共享锁实现分布式锁

面试官:你说的是排他锁,共享锁呢?

大家有没发现,上面分布式锁的实现方式是排他锁,我们也可以使用共享锁的实现方式,来看看两者的区别。

排他锁,又称为写锁或独占锁,是一种基本的锁类型。如果事务T1对数据对象O1加上了排他锁,那么在整个加锁期间,只允许事务T1对O1进行读取和更新操作,其他任何事务都不能再对这个数据对象进行任何类型的操作——直到T1释放了排他锁。

共享锁,又称为读锁,同样是一种基本的锁类型。如果事务T1对数据对象O1加上了共享锁,那么当前事务只能对O1进行读取操作,其他事务也只能对这个数据对象加共享锁——直到该数据对象上的所有共享锁都被释放。

Zookeeper以共享锁方式来实现分布式锁,每次读、写请求都会去创建子节点,这是一个类似于“/shared_lock/[Hostname]-请求类型-序号”的临时顺序节点

每一个要获得分布式锁的客户端都会去获取子节点列表,同时注册Watcher监听,读、写这两步有不同的步骤。

(1)获取读锁的话,如果前面比自己小的序号没有写请求,则表示可以读。

(2)获取写锁的话,只有在自己是序号最小的情况下,才可以读成功。

另外共享锁的释放锁和排他锁都是一样的,只需要删除所创建的子节点就可以。

3.3 共享锁羊群效应

面试官:有没听说过共享锁的羊群效应?

大家要注意下,共享锁来实现分布式锁,在集群规模比较大的场景下,可能会出现羊群效应。

什么是羊群效应?我们看看百度百科的解释。

羊群效应是个人的观念或行为由于真实的或想象的群体的影响或压力,而向与多数人相一致的方向变化的现象。

其实共享锁的特别之处,在于每次读、写请求都要注册Watcher监听来获取子节点列表,特别是数量更多的读请求,每1分钟可能是上百万次的请求。

以共享锁来实现,子节点列表只要每次一变动,就要通知所有的服务器客户端。这明显造成了短时间大量的事件通知,给Zookeeper带来的性能消耗是巨大的。

3.4 处理羊群效应

面试官:那怎么解决呢?

如何看待共享锁带来的羊群效应,我们从两个方面来看待。如果在集群不大的情况下羊群效应发生带来的影响不会太大,而且这种设计简单实用

而如果在集群规模大的场景下,我们可以这样改进。客户端的读、写请求首先获取子节点列表,但都不注册Watcher监听

(1)读请求:只向比自己序号小的最后一个写请求节点注册Watcher监听。

(2)写请求:只向比自己序号小的最后一个节点注册Watcher监听。

这样的设计就可以避免羊群效应,主要是从监听子节点列表,改进为只监听某个子节点

3.5 Kafka应用场景

面试官:Kafka应用场景呢,知道Kafka是怎么利用Zookeeper吗?

南哥了解到的Kafka利用Zookeeper的主要有 4 点,我们来看看。

(1)使用Zookeeper来对所有Broker服务器、Topic进行管理。Broker启动后都会到Zookeeper上创建属于自己的临时节点,其节点路径为/broker/ids/[0…N],注册Topic节点也是一样。

(2)而在Kafka防止消费重复消费方面,消费者消费消息后,都会在消息分区写入临时节点,代表该消息已消费。

(3)另外在Kafka生产者负载均衡方面,Kafka消息生产者会通过监听Broker节点列表,负载均衡地分发到某一个Broker。

(4)在消费者负载均衡有两方面。一方面,每一个消费者服务器都会在Zookeeper创建消费者节点。当有新消息时,Kafka就可以通过Zookeeper的消费者节点列表负载均衡地通知某个消费者;另一方面,Kafka将一个Topic分成了多个分区,多个分区由不同的Broker处理,这是实现对Broker的负载均衡

我是南哥,南就南在Get到你的点赞点赞点赞。

在这里插入图片描述

看了就赞,Java进阶一大半。点赞 | 收藏 | 关注,各位的支持就是我创作的最大动力❤️

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

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

相关文章

visionpro官方示例分析(一) 模板匹配工具 缺陷检测工具

1.需求:找出图像中的这个图形。 2.步骤 使用CogPMAlignTool工具,该工具是模板匹配工具,见名知意,所谓模板匹配工具就是说先使用该工具对一张图像建立模板,然后用这个模板在其他图像上进行匹配,匹配上了就说…

代码随想录算法训练营第六十天|Day60 图论

Bellman_ford 队列优化算法(又名SPFA) https://www.programmercarl.com/kamacoder/0094.%E5%9F%8E%E5%B8%82%E9%97%B4%E8%B4%A7%E7%89%A9%E8%BF%90%E8%BE%93I-SPFA.html 本题我们来系统讲解 Bellman_ford 队列优化算法 ,也叫SPFA算法&#xf…

LAMP环境的部署

一、软件安装介绍 在Linux系统中安装软件有rpm安装、yum安装、源码安装等方法,在这里主要给大家介绍 yum 安装,这是一种最简单方便的一种安装方法。 YUM(Yellow dog Upadate Modifie)是改进版的 RPM 管理器,很好地解…

搭建文件服务器并使用Qt实现文件上传和下载(带账号和密码)

文章目录 0 背景1 搭建文件服务器2 代码实现文件上传和下载2.1 在pro文件中添加网络支持2.2 创建网络管理类2.3 文件上传2.4 文件下载 3 扩展(其他方法实现文件上传和下载)3.1 python3.2 npm3.3 ftp服务器 4 完整的代码 0 背景 因为需要使程序具备在远程…

matlab导出3D彩色模型(surface类转stl,并对白模上色)

在matlab中绘制3维图形时,需要将3维图形导出到PPT中展示。但是直接导出图片效果欠佳,无法全方位展示。 最近学习了如何将matlab中的图形导出为stl模型,然后再采用简单的方法对模型上色。 中间尝试过matlab导出stl、ply、3dm等多种格式&…

Java项目中加缓存

Java项目中加缓存 1.更新频率低;但读写频率高的数据很适合加缓存; 2.可以加缓存的地方很多:浏览器的缓存;CDN的缓存;服务器的缓存; 本地内存;分布式远端缓存; 加缓存的时候不要…

VTK的基本概念(一)

文章目录 三维场景的基本要素1.灯光2.相机3.颜色4.纹理映射 三维场景的基本要素 1.灯光 在三维渲染场景中,可以有多个灯光的存在,灯光和相机是三维渲染场景的必备要素,如果没有指定的话,vtkRenderer会自动创建默认的灯光和相机。…

【C知道】数据包捕获(wire shark)

请解释一下数据包捕获和分析工具(如Wireshark)的工作原理和用途。 数据包捕获和分析工具,例如Wireshark(以前称为 Ethereal),是一种网络协议分析软件,它允许用户实时监控计算机网络中的数据传输…

浮点数计算,不丢失精度

在js中对于浮点数直接计算会存在精度丢失的情况,为了保证精度问题,可以做如下处理: 浮点数精度计算 主要流程如下: 浮点数转换成整数 示例代码如下 /** 将一个浮点数转成整数,返回整数和倍数。如 3.14 >> 314…

计算机网络八股整理(三)

目录 计算机网络八股(三)传输层1:说一下tcp的头部?2:tcp三次握手的过程说一下?拓展linux中查看tcp状态: 3:tcp为什么需要三次握手建立连接?4:tcp三次握手,如果…

C#基础控制台程序

11.有一个54的矩阵,要求编程序求出其中值最大的那个元素的值,以及其所在的行号和列号。 12.从键盘输入一行字符,统计其中有多少个单词,单词之间用空格分隔开。 13.输入一个数,判断它是奇数还是偶数,如果…

小程序-基于java+SpringBoot+Vue的微信小程序养老院系统设计与实现

项目运行 1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.硬件环境&#xff1a…

LeetCode—74. 搜索二维矩阵(中等)

仅供个人学习使用 题目描述: 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target ,如果 target 在矩阵中,返回 true…

命令行使用ssh隧道连接远程mysql

本地电脑A 跳板机B 主机2.2.2.2 用户名 B ssh端口号22 登录密码bbb 远程mysql C 地址 3.3.3.3 端口号3306 用户名C 密码ccc A需要通过跳板机B才能访问C; navicat中配置ssh可以实现在A电脑上访问C 如何实现本地代码中访问C呢? # 假设本地使…

海康VsionMaster学习笔记(学习工具+思路)

一、前言 VisionMaster算法平台集成机器视觉多种算法组件,适用多种应用场景,可快速组合算法,实现对工件或被测物的查找测量与缺陷检测等。VM算法平台依托海康威视在图像领域多年的技术积淀,自带强大的视觉分析工具库,可…

⭐️ GitHub Star 数量前十的工作流项目

文章开始前,我们先做个小调查:在日常工作中,你会使用自动化工作流工具吗?🙋 事实上,工作流工具已经变成了提升效率的关键。其实在此之前我们已经写过一篇博客,跟大家分享五个好用的工作流工具。…

视频汇聚平台Liveweb国标GB28181视频平台监控中心设计

在现代安防视频监控领域,Liveweb视频汇聚平台以其卓越的兼容性和灵活的拓展能力,为用户提供了一套全面的解决方案。该平台不仅能够实现视频的远程监控、录像、存储与回放等基础功能,还涵盖了视频转码、视频快照、告警、云台控制、语音对讲以及…

安装SQL Server 2022提示需要Microsoft .NET Framework 4.7.2 或更高版本

安装SQL Server 2022提示需要Microsoft .NET Framework 4.7.2 或更高版本。 原因是:当前操作系统版本为Windows Server 2016 Standard版本,其自带的Microsoft .NET Framework 版本为4.6太低,不满足要求。 根据报错的提示,点击链接…

重塑视频新语言,让每一帧都焕发新生——Video-Retalking,开启数字人沉浸式交流新纪元!

模型简介 Video-Retalking 模型是一种基于深度学习的视频再谈话技术,它通过分析视频中的音频和图像信息,实现视频角色口型、表情乃至肢体动作的精准控制与合成。这一技术的实现依赖于强大的技术架构和核心算法,特别是生成对抗网络&#xff0…

Llama-2-7b:vocab size:32000;embeddings:4096;hidden_layers是什么意思

目录 Llama-2-7b:vocab size:32000;embeddings:4096 vocab size:模型能解析词汇数量==n_vocab num_hidden_layers: 32 nanogpt隐藏层4 "initializer_range": 0.02 Token Embed是什么 举例说明 不同Chat版本的Token Embed(Token Embeddings) 区别 Llama…