其他
你能说出 Kafka 这些原理吗?
The following article comes from Java建设者 Author cxuan
Kafka 是如何进行复制的 Kafka 是如何处理来自生产者和消费者的请求的 Kafka 的存储细节是怎样的
集群成员间的关系
Kafka 可以通过 broker.id.generation.enable 和 reserved.broker.max.id 来配合生成新的 broker.id。 broker.id.generation.enable参数是用来配置是否开启自动生成 broker.id 的功能,默认情况下为true,即开启此功能。自动生成的broker.id有一个默认值,默认值为1000,也就是说默认情况下自动生成的 broker.id 从1001开始。
如果你要启动另外一个具有相同 ID 的 broker,那么就会得到一个错误 —— 新的 broker 会试着进行注册,但不会成功,因为 ZooKeeper 里面已经有一个相同 ID 的 broker。 在 broker 停机、出现分区或者长时间垃圾回收停顿时,broker 会从 ZooKeeper 上断开连接,此时 broker 在启动时创建的临时节点会从 ZooKeeper 中移除。监听 broker 列表的 Kafka 组件会被告知该 broker 已移除。 在关闭 broker 时,它对应的节点也会消失,不过它的 ID 会继续存在其他数据结构中,例如主题的副本列表中,副本列表复制我们下面再说。在完全关闭一个 broker 之后,如果使用相同的 ID 启动另一个全新的 broker,它会立刻加入集群,并拥有一个与旧 broker 相同的分区和主题。
Broker Controller 的作用
控制器的选举
控制器的作用
控制器相当于部门(集群)中的部门经理(broker controller),用于管理部门中的部门成员(broker) 控制器是所有 broker 的一个监视器,用于监控 broker 的上线和下线 在 broker 宕机后,控制器能够选举新的分区 Leader 控制器能够和 broker 新选取的 Leader 发送消息
主题管理 : Kafka Controller 可以帮助我们完成对 Kafka 主题创建、删除和增加分区的操作,简而言之就是对分区拥有最高行使权。
分区重分配: 分区重分配主要是指,kafka-reassign-partitions 脚本提供的对已有主题分区进行细粒度的分配功能。这部分功能也是控制器实现的。 Prefered 领导者选举 : Preferred 领导者选举主要是 Kafka 为了避免部分 Broker 负载过重而提供的一种换 Leader 的方案。 集群成员管理: 主要管理 新增 broker、broker 关闭、broker 宕机 数据服务: 控制器的最后一大类工作,就是向其他 broker 提供数据服务。控制器上保存了最全的集群元数据信息,其他所有 broker 会定期接收控制器发来的元数据更新请求,从而更新其内存中的缓存数据。这些数据我们会在下面讨论
broker controller 数据存储
broker 上的所有信息,包括 broker 中的所有分区,broker 所有分区副本,当前都有哪些运行中的 broker,哪些正在关闭中的 broker 。 所有主题信息,包括具体的分区信息,比如领导者副本是谁,ISR 集合中有哪些副本等。 所有涉及运维任务的分区。包括当前正在进行 Preferred 领导者选举以及分区重分配的分区列表。
broker controller 故障转移
注意:ZooKeeper 中存储的不是缓存信息,broker 中存储的才是缓存信息。
broker controller 存在的问题
controller 状态的更改由不同的监听器并发执行,因此需要进行很复杂的同步,并且容易出错而且难以调试。 状态传播不同步,broker 可能在时间不确定的情况下出现多种状态,这会导致不必要的额外的数据丢失。 controller 控制器还会为主题删除创建额外的 I/O 线程,导致性能损耗。 controller 的多线程设计还会访问共享数据,我们知道,多线程访问共享数据是线程同步最麻烦的地方,为了保护数据安全性,控制器不得不在代码中大量使用ReentrantLock 同步机制,这就进一步拖慢了整个控制器的处理速度。
broker controller 内部设计原理
副本机制
Leader 副本
Follower 副本
Kafka 中,Follower 副本也就是追随者副本是不对外提供服务的。这就是说,任何一个追随者副本都不能响应消费者和生产者的请求。所有的请求都是由领导者副本来处理。或者说,所有的请求都必须发送到 Leader 副本所在的 broker 中,Follower 副本只是用作数据拉取,采用异步拉取的方式,并写入到自己的提交日志中,从而实现与 Leader 的同步 当 Leader 副本所在的 broker 宕机后,Kafka 依托于 ZooKeeper 提供的监控功能能够实时感知到,并开启新一轮的选举,从追随者副本中选一个作为 Leader。如果宕机的 broker 重启完成后,该分区的副本会作为 Follower 重新加入。
能够立刻看到写入的消息,就是你使用生产者 API 成功向分区写入消息后,马上使用消费者就能读取刚才写入的消息 能够实现消息的幂等性,啥意思呢?就是对于生产者产生的消息,在消费者进行消费的时候,它每次都会看到消息存在,并不会存在消息不存在的情况
同步复制和异步复制
producer 通知 ZooKeeper 识别领导者 producer 向领导者写入消息 领导者收到消息后会把消息写入到本地 log 跟随者会从领导者那里拉取消息 跟随者向本地写入 log 跟随者向领导者发送写入成功的消息 领导者会收到所有的跟随者发送的消息 领导者向 producer 发送写入成功的消息
ISR
Unclean 领导者选举
Kafka 请求处理流程
这里需要注意一点,我们只是使用 HTTP 请求来举例子,而 Kafka 采用的是 TCP 基于 Socket 的方式进行通讯
响应式模型
Request type (也就是 API Key) Request version(broker 可以处理不同版本的客户端请求,并根据客户版本做出不同的响应) Correlation ID --- 一个具有唯一性的数字,用于标示请求消息,同时也会出现在响应消息和错误日志中(用于诊断问题) Client ID --- 用于标示发送请求的客户端
注意:IO 线程池可以通过 broker 端参数 num.io.threads 来配置,默认的线程数是8,表示每台 broker 启动后自动创建 8 个IO 处理线程。
请求类型
Kafka 重平衡流程
消费者订阅的任何主题发生变化 消费者数量发生变化 分区数量发生变化 如果你订阅了一个还尚未创建的主题,那么重平衡在该主题创建时发生。如果你订阅的主题发生删除那么也会发生重平衡 消费者被群组协调器认为是 DEAD 状态,这可能是由于消费者崩溃或者长时间处于运行状态下发生的,这意味着在配置合理时间的范围内,消费者没有向群组协调器发送任何心跳,这也会导致重平衡的发生。
在了解重平衡之前,你需要知道这两个角色
在了解重平衡之前,你需要知道状态机是什么
消费者组一开始处于 Empty 状态,当重平衡开启后,它会被置于 PreparingRebalance 状态等待新消费者的加入,一旦有新的消费者加入后,消费者群组就会处于 CompletingRebalance 状态等待分配,只要有新的消费者加入群组或者离开,就会触发重平衡,消费者的状态处于 PreparingRebalance 状态。等待分配机制指定好后完成分配,那么它的流程图是这样的
在上图的基础上,当消费者群组都到达 Stable 状态后,一旦有新的消费者加入/离开/心跳过期,那么触发重平衡,消费者群组的状态重新处于 PreparingRebalance 状态。那么它的流程图是这样的。 在上图的基础上,消费者群组处于 PreparingRebalance 状态后,很不幸,没人玩儿了,所有消费者都离开了,这时候还可能会保留有消费者消费的位移数据,一旦位移数据过期或者被刷新,那么消费者群组就处于 Dead 状态了。它的流程图是这样的 在上图的基础上,我们分析了消费者的重平衡,在 PreparingRebalance或者 CompletingRebalance 或者 Stable 任意一种状态下发生位移主题分区 Leader 发生变更,群组会直接处于 Dead 状态,它的所有路径如下 新成员加入组 组成员主动离开 组成员崩溃离开 组成员提交位移
重平衡流程
从消费者看重平衡
从协调者来看重平衡
新成员入组
组成员离开
组成员崩溃
重平衡时提交位移
声明:本文为作者投稿,版权归作者个人所有。
热 文 推 荐
☞在以太坊上开发 Dapp 的瓶颈和门槛有哪些?| 博文精选