文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Kafka 如何基于 KRaft 实现集群最终一致性协调

2024-11-29 21:51

关注

Zookeeper 提供了配置服务、分布式同步、命名服务、Leader 选举和集群管理等功能,在大数据时代的开始很多开源产品都依赖 Zookeeper 来构建,Apache Kafka 也不例外。但是随着 Kafka 功能的演进和应用的场景越来越多:

因此作为 Zookeeper 的替代,Kafka 3.3.1 提供了 KRaft 元数据管理组件。

下图来自于 KIP-500 [1]提案,左右分别是 Zookeeper 模式和 KRaft 模式的部署架构图。

图片

在 Zookeeper (后面简称为 ZK)模式下:

在 KRaft 模式下:

Raft 的原理和实现已经有很多优秀的文章介绍过了,就不在此赘述了。下面着重介绍一下 Kafka 如何基于 KRaft 实现集群的最终一致性协调。

二、最终一致性协调

最终一致性协调分为两部分:Controller 内存数据与 KRaft 的一致性;Broker (分区 / 配置 / ...)状态与期望的一致性。

2.1 Controller

Controller 在生产环境中通常由 3 个节点组成 Quorum,底层使用 KRaft 来进行一致性协调,KRaft 的 Leader 即是 Controller Leader。

只有 Leader 会进行请求处理,Follower 只会跟随 Replay KRaft 中的数据,请求处理流程简要如下:

  1. 当 Leader 网络层接收到 Broker 发来的请求后,会将请求首先放入到事件队列中,由后台的单线程来处理事件队列中的请求。通过单线程处理机制简化了并发编程的复杂度,并且确保所有请求可以顺序处理;
  2. 单线程处理器运行请求对应的 Manager 逻辑。Manager 根据当前内存中维护的状态,生成响应和变更的 Records;
  3. 最后再把变更的 Records 提交到 KRaft 中,等多数派确认后就可以将响应返回,并 #replay(Records) 修改 Manager 维护的内存状态;
  4. 同时 Follower 也会将 KRaft 中的 Records #replay到内存中,内存数据持续的保持同步;

以 CAS(expectValue, newValue) 举例说明上述的流程,假设内存中的初始状态为 1,Broker Client 提交了请求 CAS(1, 2) 到 Controller:

  1. 首先 Leader 会将请求放到事件队列中;
  2. 然后 Manager 以单线程模式处理请求,判断内存中的值是 1,等于请求的 expectValue,因此生成成功响应和 Record{value = 2};
  3. 最后再把变更的 Records 提交到 KRaft 中,KRaft 确认后返回给请求方响应,并将 Record{value = 2} replay 到 Manager,Manager 内存状态更新为 2;

简而言之,Controller 简版的处理时序如下:

开始处理请求 A -> Manager 生成响应和 Records -> Records 在 KRaft 多数派确认 -> Manager#replay(Records) -> 返回响应 -> 处理下一条请求...

通过上述的处理时序,Controller 就可以做到“内存状态与 KRaft ”和“多节点之间的内存状态”的一致性:

Controller 简版的处理时序在正确性上没什么问题,但在性能上有所瓶颈。假设每次 KRaft 多数派确认需要 2ms,意味着 Controller 处理请求的最大吞吐为 500 req/s。因此 Kafka 的实际处理模型中将最耗时的 KRaft 确认这步从处理时序中移除了。具体流程如下图所示:

图片

相比简版的处理时序:

Controller 处理请求的最大吞吐为:Min(1s / Manager 代码执行 CPU 耗时, KRaft 写入吞吐)。

然而先 #replay 到内存再让 KRaft 确认可能会造成内存里面有脏数据,仍旧以 CAS(1, 2) 举例,考虑如下场景:

  1. Controller Leader 的 Manager 通过 #replay 将内存值从 1 更新成 2;
  2. Leader 提交 Record{value=2}到 KRaft;
  3. 假设这时候由于心跳超时抖动等原因,导致该节点不再是 KRaft Leader 了,这时候会提交失败,返回客户端失败;
  4. 这时 Controllers 节点内存中的状态分别为 2、1、1,KRaft 中的状态为 1,集群状态不一致;

为了解决这个问题,Kafka 设计了一系列支持 MVCC 的 Timeline 数据结构:TimelineHashMap、TimelineHashSet、TimelineInteger、TimelineLong 和底层的 SnapshotRegistry。Controller 的内存状态都通过 Timeline 数据结构来维护,当出现 Leader 切换时,旧的 Leader 会将 Timeline 数据结构的数据回滚到上一个已经被 KRaft 多数派确认的状态,来保证旧 Leader 内存中不会有脏数据。

可能细心的小伙伴会发现,解决了写入的脏数据问题,那是不是可能读到还未被 KRaft 确认的数据呢?Timeline 数据结构也考虑到了这点,例如 TimelineLong 提供了 #get(epoch) 接口,其中 epoch 通常传入的是 KRaft CommitedOffset,以此来保障读到的数据都是 KRaft 确认过的数据。

对 Timeline 数据结构有兴趣的小伙伴,可以自行研究一下 server-common 模块下 org.apache.kafka.timeline 这个包的实现。

2.2 Broker

在上一章节我们提到,Controller Follower 会 #replay KRaft 中的数据来构建自己的内存状态。Broker 同理也一样会订阅 KRaft 中的 Records 来构建自己的内存元数据,并且根据这些 Records 来执行特定的变更。

以分区管理为例,假设集群有 B1 和 B2 两个节点,用户将分区 P1 从 B1 移动到 B2(简化 ISR 变更的过程):

  1. Controller 处理分区移动请求,并生成 PartitionChangeRecord{P1=B2}提交到 KRaft;
  2. B1 #replay到对应的变更记录,更新内存元数据记录 P1 在 B2 上,并开始关闭 P1;
  3. B2#replay到对应的变更记录,更新内存元数据记录 P1 在 B2 上,并开始打开 P1;

这时候 B1 和 B2 都可以通过内存元数据提供一致的的 Topic Metadata 查询服务,并且完成了分区 P1 的移动。

通过这种方式,很多变更 Controller 无需再主动调用 Broker 的 RPC 来尝试将集群推进到某个状态,也无需处理 RPC 调用中的顺序和幂等重试等问题。转换思路,Controller 通过 KRaft 来下发期望的状态,然后 Broker 去达成状态,这和 K8s 推荐的声明式管理有异曲同工之妙。

三、总结   

我们可以看出 KRaft 替换 ZK,并不是元数据存储重新造轮子,而核心是集群协调机制的演进。整个通信协调机制本质上是事件驱动模型,也就是 Metadata as an Event Log,Leader 通过 KRaft 生产权威的事件,Follower 和 Broker 通过监听 KRaft 来获得这些事件,并且顺序处理事件,达到集群状态和期望的最终一致。

参考资料

[1] KIP-500 Replace Zookeeper with a Self-Managed Metadata Quorum:https://cwiki.apache.org/confluence/display/KAFKA/KIP-500%3A+Replace+ZooKeeper+with+a+Self-Managed+Metadata+Quorum

[2] Timeline:https://github.com/apache/kafka/tree/trunk/server-common/src/main/java/org/apache/kafka/timeline

来源:AutoMQ内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯