我们都知道,自从 Kafka 诞生之际,就一直使用 Zookeeper 服务来进行 kafka 集群的元数据和状态管理,虽然在 KIP-500 中有提议未来将移除 Zookeeper 的依赖,使用 Raft 协议来实现新的元数据和状态管理,但在这之前,我们仍然需要对 kafka 集群的整个元数据和状态有一定理解,才能更好的维护和保障 kafka 集群。
前言
在 kafka 集群中,ZooKeeper 集群用于存放集群元数据
、成员管理
、Controller 选举
,以及其他一些管理类任务
。
存放元数据
: 是指主题分区的所有数据都保存在 ZooKeeper 中,且以它保存的数据为权威,其他 “人” 都要与它保持对齐。成员管理
: 是指 Broker 节点的注册、注销以及属性变更。Controller 选举
: 是指选举集群 Controller,而其他管理类任务包括但不限于主题删除、参数配置。
Zookeeper 服务
在开始之前,我们首先需要对 Zookeeper 服务有一定的了解。在官方文档中,Zookeeper 有如下能力:
- 配置管理:其实就是单纯的 K/V 存储,可以用来配置的存储和管理,实现对分布式系统组件的集中式的配置管理
- 命名:命令空间管理,在 zookeeper 中配置可通过不同的根路径来实现简单的命名空间隔离 (简单的 chroot 隔离)
- 分布式的同步服务:可保证分布式的同步
- 分组服务:可以将一组服务配置进行分组管理,其实在 Dubbo 的注册中心中,就是使用分组和命名来统一进行生产者的注册和发现
![Zookeeper架构 Zookeeper架构](https://tva1.sinaimg.cn/large/007S8ZIlly1gg095r9zy2j30go0553z6.jpg)
在 Zookeeper 中所有的命名空间和文件系统比较类似,每个节点都有一个唯一的路径
,如下图:
![zookeeper内部存储结构 zookeeper内部存储结构](https://tva1.sinaimg.cn/large/007S8ZIlly1gg09dvjkrnj30ca071mxh.jpg)
为什么 Zookeeper 服务可以满足配置管理和协调服务呢?主要是因为它的节点属性,通常也是经常可能会忽略的问题,即在 Zookeeper 中存在两种节点: 持久节点
和临时节点
,节点也称之为 znode
,而 znode 本身除了数据之外,还会存储一些额外的信息:
- 数据变更的版本号
- ACL 变更的版本号
- 时间戳
每次 znode 中的数据有变更,版本号都会递增,并且 client 在向 znode 获取数据时,不仅会获取实际数据,而且会获取到数据的版本,这在整个配置管理领域会相当有用。
前面说到的持久节点
只要 znode 创建后,便一直会存在,这种节点主要用于配置的持久化存储,只要 zookeeper 集群整体可用,那该节点也一直可用 (及时集群异常后恢复,该节点依旧存在);而临时节点
随着某个创建 znode 的会话的开始,被创建,而一旦这个会话被撤除掉,这个 znode 就会自动被 ZooKeeper 删除。
对于临时节点
来讲,经常会被用在如下场景:
- dubbo 中的服务注册
- 其他分布式服务中的 leader 选举
而真正使得 Zookeeper 在 Java 语言生态中有如此大影响还依赖于另外一个功能: watches
,Client 可以对某个 znode 设置 watch
当这个 znode 有变更的时候,就会产生 watch
事件,这个事件会由 ZooKeeper 通知至 Client, 即是 Client 会收到来自 Server 的通知,可以实现数据的动态变更。(之所以说是 Java 语言生态,是因为在云原生领域,Etcd 几乎是 Zookeeper 的替代品,不同的是它是 Golang 语言生态体系中的)
kafka 集群数据在 zookeeper 的存储
前面对 Zookeeper 服务进行了大概的说明,接下来我们一起看看 kafka 的集群数据在 zookeeper 中是如何存储和分布的。<