北京 网站设计招聘信息/今日头条官网
欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送!
在我后台回复 「资料」 可领取
编程高频电子书
!
在我后台回复「面试」可领取硬核面试笔记
!文章导读地址:点击查看文章导读!
感谢你的关注!
一篇文章了解 ZooKeeper 底层运行原理
该文章主要说一下 ZooKeeper 底层运行原理,以及其中比较核心的功能
CAP 是分布式系统中的基本理论,一般只能满足 AP 和 CP,常用的注册中心 ZK 和 Nacos:
- ZooKeeper 符合 CP ,选择了一致性而抛弃了部分可用性 ,因为 ZK 集群中只有 Leader 节点可以写数据,如果 Leader 挂了,需要重新选举 Leader,在这期间 ZK 集群不可用,ZK 只有 Leader 可以写,所以整个写入操作是 中心化 的
- Nacos 符合 AP ,选择了可用性并且满足最终一致性 ,并且 Nacos 的设计是去中心化的
并且由于 ZK 的监听机制,导致在节点数量较多的时候,如果出现大量监听事件的触发,会导致 ZK 瞬时流量过大 ,因此,现在将 Zookeeper 作为服务注册中心的公司在减少,而是转向使用 Nacos 或自研注册中心
首先说一下 ZooKeeper 用来做什么
ZooKeeper 是一个分布式协调服务,提供了一个中心化的服务,用于管理和协调分布式应用中的各种配置、信息和事件
那么一般使用 ZooKeeper 中,较常用的场景就是 注册中心 、 元数据管理
元数据管理 指对多个分布式服务中都需要用到的基础类型的数据进行管理,使用 ZK 管理的好处就是不需要在每一个分布式服务中都进行配置,只要在 ZK 中进行配置即可,并且配置变更之后,所有的分布式服务可以及时收到 数据变更的通知
注册中心 指在那些需要进行 RPC 远程调用时,将 RPC 服务注册到 ZK 中去,之后需要调用的话,可以在 ZK 中查询提供了哪些服务可以进行调用,并且可以进行 负载均衡 处理
如下图,如果提供了一个 HelloServiceImpl 的 RPC 服务,将该服务注册在 ZK 中,节点值为该服务的 IP 地址,这样调用方在需要使用服务的时候,可以拿到该服务的 IP 地址,与该服务建立 TCP 连接即可进行通信(Dubbo 的注册中心可以使用 ZK 也可以使用 Nacos)
ZooKeeper 中的核心内容
ZooKeeper 中的核心内容如下:
- 节点类型
- watcher 监听机制
- 分布式锁
- 集群模式
接下来主要从这几块内容来介绍 ZooKeeper 的运行原理
节点类型
ZK 中的节点类型分为:持久节点、临时节点、顺序节点
持久节点:创建之后一直存在
临时节点:只要客户端断开连接,节点就会被删除
顺序节点:创建节点时,会添加全局递增的序号,经典应用场景是 分布式锁 (顺序节点既可以是持久节点也可以是临时节点)
节点使用应用场景: 在 RPC 调用中,将提供的 RPC 服务作为临时节点注册在 ZK 中,当 RPC 服务提供者与 ZK 断开连接之后,该服务在 ZK 中注册的临时节点就会被删除,那么我们客户端就可以对该节点添加监听器,当发现节点被删除之后,就可以感知到对应的服务下线了(监听器的内容会在后边说道)
ZooKeeper 的监听机制
ZooKeeper 提供了 watcher 监听机制,这是 ZK 中最常用的功能,因为多个分布式节点之间及时感知到 ZK 数据的变化就是通过 监听机制实现的
ZK 中的 watcher 有以下几个特点:
- 一次性: watcher 被触发之后,ZK会将其从客户端的 WatchManager 中删除,也会从服务端删除,重新注册 watcher 才可以继续下一次的监听
- 串行性: 同一 Node 的相同事件类型引发的 watcher 回调方法串行执行(也就是只有执行完w atcher 的回调,才可以重新生成 watcher 对象进行监听,如果回调执行时间太长,可能会导致监听事件的丢失,因此 ZK 也不适合在 watcher 回调中执行耗时的IO操作)
上边说的 watcher 监听是 ZK 中原生的监听机制,我们使用 ZK 都是使用它的客户端工具 Curator,该客户端工具中也封装了一些丰富的功能来提供给我们进行使用,如 分布式锁 、节点监听机制
这里说一下 Curator 提供的节点监听机制 ,提供了有 3 种类型的监听:
- NodeCache :监听指定节点(单个节点监听)
- PathChilrenCache :监听指定节点的子节点
- TreeCache :监听指定节点
那么对于 监听机制的使用 ,这里还是以 RPC 远程服务调用为例,如果每一个 RPC 服务提供者都会将自己的 IP 地址注册到对应的节点下,那么客户端只需要对 com.zqy.service.impl.HelloServiceImpl 这个节点下的子节点进行监听,就可以感知到哪些服务已经下线,就不再对该服务进行远程调用即可,那么这里就可以使用 PathChildrenCache 来进行监听(具体的代码示例这里就不写了,只讲原理)
分布式锁
ZK 作为分布式协调框架,用来作为分布式锁使用从他的设计目的上来讲是比较合适的,那么常用的分布式锁还有 Redis 的分布式锁(Redisson 客户端框架提供)
- 对于这两种锁到底要如何去选择使用呢?
其实使用哪一种都可以,两者提供的分布式锁功能都可以满足日常的使用,并且使用 Redis 集群和使用 ZK 集群都可以保证较好的锁的可用性
但是两者在 极端情况下也会出现问题 ,如在 Redis 集群加锁,写入主节点之后,如果锁的信息未来得及同步到从节点,此时主节点宕机,就会导致这个锁的信息丢失,会出现 重复加锁 的情况;在 ZK 集群中,如果客户端长时间 GC 导致无法与 ZK 维持心跳,ZK 会误认为该客户端下线,将该客户端加锁的临时节点删除,也会出现 重复加锁 的情况
那么可以看到在 功能性 和 可用性 上,两者其实差别都不大,具体选用的话,可以 根据当前项目使用的技术栈 来进行选择,比如当前项目中并没有引入 Redis 依赖,只有 ZK 依赖,那么直接使用 ZK 的分布式锁,完全没有必要去引入 Redis 集群来使用 Redis 的分布式锁,因为多一种技术,就多一份故障的风险,单单为了使用 Redis 分布式锁就去引入 Redis 集群显然小题大做了
- ZK 中的分布式锁实现
ZK 的分布式锁就是依靠 临时顺序节点 实现的,比如说创建一把名为 lock 的锁,那么所有需要加锁的客户端会到该节点下创建 临时顺序节点 ,只有第一个创建成功的客户端可以拿到锁,其他客户端创建的临时顺序节点在后边排序,并且对前一个节点进行 监听 ,当监听到锁释放,自己就拿到了锁(可以了解一下 Curator 对读写锁出现的羊群效应的解决)
ZooKeeper 集群
接下来说一下 ZK 的集群部署,ZK 集群中通过分布式一致性协议 ZAB 来保证数据同步的一致性,以及 Leader 选举、集群的崩溃恢复,接下来会主要 围绕 ZAB 协议 来说一下 ZK 集群相关的核心内容:
ZK 集群中有三种角色:Leader、Follower、Observer
- Leader :执行写操作,并且向 Follower 进行同步
- Follower :从 Leader 同步数据,执行读操作,不可以执行写操作
- Observer :只可以执行读操作
ZK 集群其实是适合 写少读多 场景的,因为整个集群只有 1 个 Leader 可以写,其他节点只可以读,那么你可能有疑问,Follower 节点用来读数据,为什么还需要 Observer 节点呢?
这是因为在集群中 Leader 完成写请求是需要经过半数以上的 Follower 都 Ack 之后,才可以成功写入的,如果集群中 Follower 过多,会大大增加 Leader 节点等待 Follower 节点发送 Ack 的时间,导致 ZK 集群性能很差,因此 ZK 集群部署都是 小集群部署 ,一般都是 3 台或者 5 台机器
Observer 节点Observer 是只读的、不参与 Leader 选举、也不参与 ZAB 协议同步时过半 Ack 的环节,只是单纯的接收数据,同步数据,达到数据顺序一致性的效果,当读并发请求过高时,可以 通过不断添加 Observer 节点来分散读请求的压力
- ZK 的分布式一致性协议 ZAB 保证数据同步的一致性
ZAB 协议中是采用 2PC 两阶段提交思想完成数据写入的:
采用 2PC 两阶段提交思想 的 ZAB 消息广播流程:
每一个消息广播的时候,都是基于 2PC 的思想,先是发起事务提议 Proposal 的广播,各个 Follower 返回 Ack,当过半的 Follower 都返回 Ack 之后,Leader 就发送 Commit 消息到 Follower,让大家提交事务
这里的两阶段指的就是发送 Proposal 和 Commit !
发起一个事务 Proposal 之前,Leader 会分配一个全局唯一递增的事务 id(zxid),以此来严格保证顺序
Leader 会为每个 Follower 创建一个队列,里边存放要发给 Follower 的事务 Proposal,保证了一个同步的顺序性
Follower 收到事务 Proposal 之后,就立即写入本地磁盘日志中,写入成功后数据就不会丢失了,之后返回 Ack 给 Leader,当过半的 Follower 都返回 Ack,Leader 推送 Commit 消息给全部 Follower,让大家进行事务提交,事务提交之后,数据就被写入到了 znode(也就是内存中) ,此时数据就可以被用户感知到了
- ZK 的 ZAB 保证集群的崩溃恢复
下边将会介绍 ZK 集群 启动 再到 崩溃 再到 恢复 整体的流程:
ZK 集启动的时候,进入 恢复模式 ,选举一个 Leader 出来,然后 Leader 等待集群中过半的 Follower 跟他进行数据同步,只要过半的 Follower 完成数据同步,接着就退出恢复模式,可以对外提供服务了
此时,还没完成同步的 Follower 会自己去跟 Leader 进行数据同步的
之后会进入 消息广播模式 ,只有 Leader 可以接受写请求,但是客户端可以任意连接 Leader 或者 Follower,如果客户端连接到 Follower,Follower 就会将写请求转发给 Leader
Leader 收到写请求,就把请求同步给所有的 Follower,当超过半数的 Follower 都返回了 Ack,之后 Leader 先将数据写到自己的 znode 中,再给所有的 Follower 发一个 Commit 消息,让大家提交这个请求事务,Follower 收到 Commit 消息后,就会将磁盘中刚刚写入的数据往内存中的 znode 中写,之后客户端就可以读取到数据了
如果 Leader 宕机了,就会进入 恢复模式 ,重新选举一个 Leader,只要获得了过半的机器的投票,就可以成为 Leader
ZK 集群中可以容忍不超过一半的机器宕机,就比如说一个集群有 3 台机器,那么最多允许 1 台机器宕机,剩下的 2 台选举 Leader,只要 2 台机器都认可其中一台机器当 Leader,也就是超过了集群一半的机器都认可,那么就可以选举这台机器作为 Leader
新的 Leader 等待过半的 Follower 跟他同步,之后重新进入 消息广播模式
以上就是 ZK 集群恢复崩溃的整个流程了,当然我也画了一个流程图,更方便观看,如下:
主要就是分为 3 个阶段:
-
集群启动时:恢复模式,Leader 选举 + 数据同步
-
消息写入时:消息广播模式,Leader 采用 2PC 的过半写机制,给 Follower 进行同步
-
崩溃恢复:恢复模式,Leader/Follower 宕机,只要剩余机器超过一半,就可以选举新的 Leader
-
ZK 集群的性能瓶颈在哪里呢?
瓶颈在于 Leader 的 写性能
,如果 ZK 集群挂掉的话,那么很有可能就是 Leader 的写入压力过大,这对一个公司的技术平台打击是巨大的,因为像 kafka 之类的技术都是强依赖 ZK 的,Dubbo + ZK 去做服务框架的话,当服务实例达到上万甚至几十万时,大量服务的上线、注册、心跳的压力达到了每秒几万甚至十万,单个 Leader 抗几万的请求还行,十几万的话 ZK 单个 Leader 是扛不住这么多的写请求的
想要提升 Leader 的 写性能 ,目前来说也就是提升部署 ZK 的机器性能了,还有一种方式也就是将 dataLogDir 目录挂载的机器上配置 SSD 固态硬盘,以此来提升事务日志 写速度 来提升写性能!
- ZK 集群的 Leader 选举
在 Leader 选举时,需要用到以下几个属性:
SID :服务器 ID,和 myid 一致,作为服务器的标识,不可以重复
ZXID :事务 ID,用来标识一次服务状态的变更,ZXID 全局唯一并且递增,有 64 位,高 32 位时 Leader 的 Epoch,低 32 位是递增计数器
Epoch :每个 Leader 任期的代号(没有 Leader 时,同一轮投票过程中的 Epoch 时相同的,每投完一次票,就会加 1)
当一台机器进入 Leader 选举时,当前集群可能处于以下两种状态:
- 集群中已经有一个 Leader
如果已经有 Leader 的情况,会被告知当前服务器的 Leader 信息,之后进行状态同步即可
- 集群中确实不存在 Leader
假设 zookeeper 有 5 台服务器,SID 分别为 1、2、3、4、5,ZXID 分别为 8、8、8、7、7,并且 SID = 3 的服务器是 Leader
如果某一时刻服务器 3 和 5 出现故障,之后服务器 1、2、4 开始 Leader 选举,规则如下:
1、EPOCH 大的选举为 Leader
2、EPOCH 相同,事务 ID 大的选举为 Leader
3、事务 ID 相同,SID 大的选举为 Leader
那么对于服务器 1、2、4 来说,最终服务器 2 选举为 Leader, 这样的选举策略可以保证有 最新数据的节点 可以竞选
相关文章:

【Java核心能力】一篇文章了解 ZooKeeper 底层运行原理
欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术的推送! 在我后台回复 「资料」 可领取编程高频电子书! 在我后台回复「面试」可领取硬核面试笔记! 文章导读地址…...

P2123皇后游戏
P2123皇后游戏 参考题解 #include <iostream> #include <algorithm> using namespace std;int T; int n; long long res;struct Person {int a,b,d; }p[20005];bool person_cmp(const Person& x,const Person& y) {if(x.d y.d){if(x.d < 0)return x.a …...

git之目前的主流版本
官方文档 简介 我们都知道,在开发过程中,版本控制是至关重要的。Git作为目前最为流行的版本控制系统,已经成为了开发者们的标配。出于好奇,本人对git目前主流几大版本(GitLab、GitHub、Gitee 和 GitCode)…...

PyQT5学习--新建窗体模板
目录 1 Dialog 2 Main Window 3 Widget Dialog 模板,基于 QDialog 类的窗体,具有一般对话框的特性,如可以模态显示、具有返回值等。 Main Window 模板,基于 QMainWindow 类的窗体,具有主窗口的特性,窗口…...

企业产品网络安全建设日志0328
文章目录 Actuator再次暴露域名上线基线检查初见效果WAF更新遇波折301跳转推进中 Actuator再次暴露 为了验证挖f的拦截效果,自己随手拼了个Actuator,结果可以访问到公司的actuator。。 据称是某网关更换新组件后未做防御,已要求全部做防御&a…...

QT(C++)-error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“2”不匹配值“0”
1、项目场景: 在VS中采用QT(C)调试时,出现error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“2”不匹配值“0”错误 2、解决方案: 在“解决方案资源管理器”中选中出现此类BUG的项目,右键-…...

【 MyBatis 】| 关于多表联查返回 List 集合只查到一条的 BUG
目录 一. 🦁 写在前面二. 🦁 探索过程2.1 开端 —— 开始写 bug2.2 发展 —— bug 完成2.3 高潮 —— bug探究2.4 结局 —— 效果展示 三. 🦁 写在最后 一. 🦁 写在前面 今天又是 BUG 气满满的一天,一个 xxxMapper.xm…...

PL/SQL的词法单元
目录 字符集 标识符 分隔符 注释 oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 PL/SQL块中的每一条语句都必须以分号结束。 一个SQL语句可以跨多行,但分号表示该语句的结束:一行中也可以有多条 SQL语句&…...

第三十二天-PythonWeb主流框架-Django框架
目录 1.介绍 发展历史 介绍 2.使用 1.安装 2.创建项目 3.项目结构 4.启动 3.开发流程 1.设置ip可访问 2.创建模块 3.第一个页面 4.视图 5.include()参数 6.url与视图的关系 7.响应内容 4.视图处理业务逻辑 1.响应html 2.获取url参数 3.从文件响应html内容 …...

利用python搭建临时文件传输服务
场景 如果想从一台服务器上传输文件又多种方法,其中常见的是利用scp进行传输,但是需要知道服务器的账号密码才能进行传输,但有时候我们并不知道账号密码,这个时候我们就可以通过python -m SimpleHTTPServer 命令进行传输文件 启…...

详解 WebWorker 的概念、使用场景、示例
前言 提到 WebWorker,可能有些小伙伴比较陌生,不知道是做什么的,甚至不知道使用场景,今天这篇文章就带大家一起简单了解一下什么是 webworker! 概念 WebWorker 实际上是运行在浏览器后台的一个单独的线程,因此可以执行一些耗时的操作而不会阻塞主线程。WebWorker 通过…...

IOS面试题编程机制 6-10
6. 如何理解MVVM设计模式?MVVM即 Model-View-ViewModel 1.View主要用于界面呈现,与用户输入设备进行交互 2.ViewModel是MVVM架构中最重要的部分,ViewModel中包含属性,方法,事件,属性验证等逻辑,负责View与Model之间的通讯 3.Model就是我们常说的数据模型,用于数据的构造…...

seleniumui自动化实例-邮箱登录
1.登录163邮箱源码: from selenium import webdriver driver webdriver.Firefox() driver.get("http://www.163.com") driver.find_element_by_id("id").clear() driver.find_element_by_id("id").send_keys("用户名")…...

力扣练习 3.27
121. 买卖股票的最佳时机 贪婪思想:力争在最低成本买入,最高利润卖出。 [7,1,5,3,6,4] 可以先假设在第一天买入和卖出,这时最低成本是7,最大利润是7-70 然后假设在第二天买入和卖出,成本就是1,利润也是0 第…...

C 指向指针的指针
指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。通常,一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。 一个指向指针的指针变量…...

通俗易懂:新生代、老年代和永久代/元空间的具体含义是什么?
在Java虚拟机(JVM)的内存管理中,堆内存通常被划分为几个不同的区域,以便更有效地管理和回收内存。以下是新生代(Young Generation)、老年代(Old Generation)和永久代/元空间…...

Centos7.9备份mysql数据库
1. 备份 备份shell脚本 [rootiZoqvrzbtnzd6kZ local]# vi mysql_backup.sh #!/bin/bash #设置MySQL登录信息 MYSQL_USER"root" MYSQL_PASSWORD"**********" MYSQL_DATABASE"ubox" BACKUP_DIR"/usr/local/mysql_backup" MONTH"…...

Automatic Prompt Engineering
让大模型自己生成prompt,生成提示(prompt)存在两种不同的操作方式。第一种方式是在文本空间中进行,这种提示以离散的文本形式存在。第二种方式是将提示抽象成一个向量,在特征空间中进行操作,这种提示是抽象…...

Spring高级面试题-2024
Spring 框架中都用到了哪些设计模式? 1. 简单工厂: ○ BeanFactory:Spring的BeanFactory充当工厂,负责根据配置信息创建Bean实例。它是一种工厂模式的应用,根据指定的类名或ID创建Bean对象。2. 工厂方法ÿ…...

用BSP优化3D渲染
3D渲染引擎设计者面临的最大问题之一是可见性计算:只必须绘制可见的墙壁和物体,并且必须以正确的顺序绘制它们(应该在远处的墙壁前面绘制近墙) 。 更重要的是,对于游戏等应用程序来说,开发能够快速渲染场景…...

Composer常见错误解决
Composer 是 PHP 社区广泛使用的一个依赖管理工具,它帮助开发者定义、管理和安装项目所需的库。在使用 Composer 的过程中,可能会遇到各种错误和问题。以下是一些常见的 Composer 错误及其解决方法: 1. 内存限制错误 错误信息:P…...

amazon中sns的使用
使用网页配置订阅 创建主题>使用标准>自定义名称>其他默认 点击创建即可 创建订阅 订阅策略配置(不配置,会推送给多个人,除非你每个都创建主题) 注意: 可以你可以随便写,后面的值只能是对象&am…...

web前端面试题----->VUE
Vue的数据双向绑定是通过Vue的响应式系统实现的。具体原理: 1. Vue会在初始化时对数据对象进行遍历,使用Object.defineProperty方法将每个属性转化为getter、setter。这样在访问或修改数据时,Vue能够监听到数据的变化。 2. 当数据发生变化时…...

计算机领域热门技术词汇
文章目录 计算机领域热门技术词汇1、机器学习 machine learning2、神经网络 neural network3、深度学习 deep learning4、自然语言处理 natural language processing5、计算机视觉 computer vision6、大数据 big data7、数据挖掘 data mining(DM)8、云计…...

jsp指令和动作
1.page指令:描述页面信息 pageENcoding:软件编码 contentType:浏览器编码 2.include指令:将多个网页合成一个网页,静态包含网页 问题:1.在网页源代码中,会形成错误的多遍代码,将主页面代码和…...

手撕算法-最小覆盖子串
描述 分析 滑动窗口。 参考力扣官方的题解思路 本问题要求我们返回字符串 s 中包含字符串 t 的全部字符的最小窗口。我们称包含 t 的全部字母的窗口为「可行」窗口。 我们可以用滑动窗口的思想解决这个问题。在滑动窗口类型的问题中都会有两个指针,一个用于「延伸…...

TrOCR—基于Transformer的OCR入门
导 读 本文主要介绍TrOCR:基于Transformer的OCR入门。 背景介绍 多年来,光学字符识别 (OCR) 出现了多项创新。它对零售、医疗保健、银行和许多其他行业的影响是巨大的。尽管有着悠久的历史和多种最先进的模型,研究人员仍在不断创新。与深…...

WIN使用LPD协议来共享打印机含统信UOS
打开“控制面板”,“程序和功能”,“启动或关闭Windows功能”,下拉找到“打印和文件服务”,勾选“LPD打印服务”和“LPR端口监视器”。确定之后重启电脑,共享主机和其它需要添加共享打印机的都开启功能和重启。 一、启…...

huawei 华为 交换机 配置 LACP 模式的链路聚合示例 (交换机之间直连)
组网需求 如 图 3-22 所示, SwitchA 和 SwitchB 通过以太链路分别都连接 VLAN10 和 VLAN20 的网络,且SwitchA 和 SwitchB 之间有较大的数据流量。用户希望 SwitchA 和 SwitchB 之间能够提供较大的链路带宽来使相同VLAN 间互相通信。在两台 Switch 设备上…...

c++ 有名对象和匿名对象
c 有名对象和匿名对象 有名对象就是有名字的对象,匿名对象就是没有名字的对象。 #define _CRT_SECURE_NO_WARNINGS 1 using namespace std; #include<iostream> class score { public:score(){math 100;chinese 100;english 100;}score(int _math, int _…...