共计 2836 个字符,预计需要花费 8 分钟才能阅读完成。
简略理解 Zookeeper
Tips: 如果之前对 Zookeeper 不理解的话,这里大略留个印象就好了
Zookeeper 是一个分布式协调服务,能够用于元数据管理、分布式锁、分布式协调、公布订阅、服务命名等等。
例如,Kafka中就是用 Zookeeper 来保留其集群中的相干元数据,例如 Broker、Topic 以及 Partition 等等。同时,基于 Zookeeper 的 Watch 监听机制,还能够用其实现公布、订阅的性能。
在平时的惯例业务应用场景下,咱们简直只会应用到 分布式锁 这一个用处。
Zookeeper 外部运行机制
Zookeeper 的底层存储原理,有点相似于 Linux 中的文件系统。Zookeeper 中的文件系统中的每个文件都是节点(Znode)。依据文件之间的层级关系,Zookeeper 外部就会造成这个这样一个文件树。
在 Linux 中,文件(节点)其实是分类型的,例如分为文件、目录。在 Zookeeper 中同理,Znode 同样的有类型。在 Zookeeper 中,所有的节点类型如下:
- 长久节点(Persistent)
- 长久程序节点(Persistent Sequential)
- 长期节点(Ephemeral)
- 长期程序节点(Ephemeral Sequential)
所谓 长久节点,就和咱们本人在电脑上新建一个文件一样,除非你被动删除,否则始终存在。
而 长久程序节点 除了继承了长久节点的个性之外,还会为其下创立的子节点保障其先后顺序,并且会主动地为节点加上 10 位 自增序列号 作为节点名,以此来保障节点名的唯一性。这一点上图中的 subfiles
曾经给出了示例。
而 长期节点 ,其生命周期和 client 的连贯是否沉闷相干,如果 client 一旦断开连接,该节点(能够了解为文件)就都会被删除,并且长期节点 无奈创立子节点;
PS:这里的 断开连接 其实不是咱们直觉上了解的断开连接,Zookeeper 有其 Session 机制,当某个 client 的 Session过期 之后,会将对应的 client 创立的节点全副删除
Zookeeper 的节点创立形式
接下来咱们来别离看看几种节点的创立形式,给出几个简略的示例。
创立长久节点
create /node_name SH 的全栈笔记
这里须要留神的是,命令中 所有的节点名称必须要以 /
结尾 ,否则会创立失败,因为在 Zookeeper 中是不能应用相对路径, 必须 要应用绝对路径。
创立长久程序节点
create -s /node_name SH 的全栈笔记
能够看到,Zookeeper 为 key 主动的加上了 10 位的自增后缀。
创立长期节点
create -e /test SH 的全栈笔记
创立长期程序节点
create -e -s /node_name SH 的全栈笔记
Zookeeper 的用处
咱们通过一些具体的例子,来理解 Zookeeper 的具体用处,它不仅仅只是被当作 分布式锁 应用。
元数据管理
咱们都晓得,Kafka 在运行时会依赖一个 Zookeeper 的集群。Kafka 通过 Zookeeper 来治理集群的相干元数据,并通过 Zookeeper 进行 Leader 选举。
Tips: 然而行将公布的 Kafka 2.8 版本中,Zookeeper 曾经不是一个必须的组件了。这块我临时还没有工夫去细看,不过我预计可能会跟 RocketMQ 中解决的形式差不多,将其集群的元数据放到 Kafka 自身来解决。
分布式锁
基于 Zookeeper 的分布式锁其实流程很简略。首先咱们须要晓得加分布式锁的 实质 是什么?
答案是创立长期程序节点
当某个客户端 加锁
胜利之后,实际上则是胜利的在 Zookeeper 上创立了 长期程序节点 。咱们晓得,分布式锁可能使 同一时间 只能有一个可能拜访某种资源。那这就必然会波及到分布式锁的竞争,那问题来了,以后这个客户端是如何感知抢到了锁呢?
其实在客户端侧会有肯定的逻辑,假如加锁的 key 为/locks/modify_users
。
首先,客户端会发动加锁申请,而后会在 Zookeeper 上创立 长久节点locks
,而后会在该节点下创立长期程序节点。长期程序节点的创立示例,如下图所示。
当客户端胜利创立了节点之后,还会获取其同级的所有节点。也就是上图中的所有 modify_users000000000x
的节点。
此时客户端会依据 10 位的自增序号 去判断,以后本人创立的节点是否是所有的节点中最小的那个,如果是 最小的 则本人获取到了 分布式锁。
你可能会问,那如果我不是最小的怎么办呢?而且我的节点都曾经创立了。如果不是最小的,阐明以后客户端 并没有抢到锁 。依照咱们的认知,如果没有竞争到分布式锁,则会期待。 期待 的底层都做了什么?咱们用理论例子来捋一遍。
假如 Zookeeper 中曾经有了如下的节点。
例如 以后客户端是 B 创立的节点是 modify_users0000000002
,那么很显著 B 没有抢到锁 ,因为曾经有比它还要小的由 客户端 A 创立的节点modify_users0000000001
。
此时客户端 B 会对节点 modify_users0000000001
注册一个 监听器,对于该节点的任意更新都将触发对应的操作。
当其被删除之后,就会唤醒客户端 B 的线程,此时客户端 B 会再次进行判断本人是否是序号最小的一个节点,此时 modify_users0000000002
显著是最小的节点,故客户端 B 加锁胜利。
为了让你更加直观的理解这个过程,我把流程稀释成了上面这幅流程图。
分布式协调
咱们都晓得,在很多场景下要保障一致性都会采纳经典的 2PC(两阶段提交),例如 MySQL 中 Redo Log 和 Binlog 提交的数据一致性保障就是采纳的 2PC,详情能够看基于 Redo Log 和 Undo Log 的 MySQL 解体复原流程。
在 2PC 中存在两种角色,别离是 参与者(Participant)和 协调者(Coordinator),协调者负责对立的调度所有分布式节点的执行逻辑。具体协调啥呢?举个例子。
例如在 2PC 的 Commit 阶段,两个参与者 A、B,A 的 commit 操作胜利了,但可怜的是 B 失败了。此时协调者就须要向 A 发送 Rollback 操作。Zookeeper 大略就是这样一个角色。
公布订阅
因为 Zookeeper 自带了 监听器(Watch)的性能,所以 公布订阅 也牵强附会的成为了 Zookeeper 的利用之一。例如在某个配置节点上注册了监听器,那么该配置一旦公布变更,对应的服务就能实时的感知到配置更改,从而达到配置的动静更新的目标。
给个简略的 Watch 应用示例。
命名服务
用大白话来说,命名服务次要有两种。
- 单纯的利用 Zookeeper 的文件系统个性,存储结构化的文件
- 利用文件个性和 程序节点 的个性,来生成全局的惟一标识
前者能够用于在零碎之间共享某种业务上的特定资源,后者则能够用于实现分布式锁。
欢送微信搜寻关注【SH 的全栈笔记 】,回复【 队列】获取 MQ 学习材料,蕴含根底概念解析和 RocketMQ 具体的源码解析,继续更新中。
好了以上就是本篇博客的全部内容了,如果你感觉这篇文章对你有帮忙,还麻烦 点个赞 , 关个注 , 分个享 , 留个言。