脱离ZooKeeper依赖的Kafka Controller Quorum(KRaft)机制浅析

2023-12-14 03:50

本文主要是介绍脱离ZooKeeper依赖的Kafka Controller Quorum(KRaft)机制浅析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

点击上方蓝色字体,选择“设为星标

回复”资源“获取更多资源

前言

相信这几天大家正在被“Kafka要弃用ZooKeeper”的消息刷屏,并且无一例外地将其视为这个老当益壮的消息系统近年来最重大的变革。当然,由于ZooKeeper在Kafka中承担了Controller选举、Broker注册、TopicPartition注册与Leader选举、Consumer/Producer元数据管理和负载均衡等等很多任务,使Kafka完全摆脱ZooKeeper的依赖也不是一朝一夕就能完成的事情。

本文挑选一个较为基础而重要的方面做简单的说明,即基于Raft共识协议的Controller Quorum机制。看官若不了解Raft协议,请务必先阅读这篇文章获取前置知识。

从单点Controller到Controller Quorum

现阶段的Controller本质上就是Kafka集群中的一台Broker,通过ZK选举出来,负责根据ZK中的元数据维护所有Broker、Partition和Replica的状态。但是,一旦没有了ZK的辅助,Controller就要接手ZK的元数据存储,并且单点Controller失败会对集群造成破坏性的影响。因此,在将来的版本中,Controller会变为一个符合Quorum原则(过半原则)的Broker集合,如下图所示。

也就是说,在实际应用中要求Controller Quorum的节点数为奇数且大于等于3,最多可以容忍(n / 2 - 1)个节点失败。当然,只有一个节点能成为领导节点即Active Controller,领导选举就依赖于内置的Raft协议变种(又称为KRaft)实现。按照介绍Raft的思路,首先来看看Controller Quorum节点的状态与转移规则。复制状态机的理论请见参考文章。

Quorum节点状态机

在KRaft协议下,Quorum中的一个节点可以处于以下4种状态之一。

  • Candidate(候选者)——主动发起选举;

  • Leader(领导者)——在选举过程中获得多数票;

  • Follower(跟随者)——已经投票给Candidate,或者正在从Leader复制日志;

  • Observer(观察者)——没有投票权的Follower,与ZK中的Observer含义相同,本文暂不考虑。

状态转换图如下所示。看官可以与经典Raft协议的状态转换图对比一下,基本是相似的。

消息定义

经典Raft协议只定义了两种RPC消息,即AppendEntries与RequestVote,并且是以推模式交互的。为了适应Kafka环境,KRaft协议以拉模式交互,定义的RPC消息有如下几种。

  • Vote:选举的选票信息,由Candidate发送;

  • BeginQuorumEpoch:新Leader当选时发送,告知其他节点当前的Leader信息;

  • EndQuorumEpoch:当前Leader退位时发送,触发重新选举,用于graceful shutdown;

  • Fetch:复制Leader日志,由Follower/Observer发送——可见,经典Raft协议中的AppendEntries消息是Leader将日志推给Follower,而KRaft协议中则是靠Fetch消息从Leader拉取日志。同时Fetch也可以作为Follower对Leader的活性探测。

根据KIP-595的说明,采用拉模式可以将一致性检查的工作放在Leader端,同时也可以更快速地bootstrap一个全新的Follower(直接从offset 0开始复制日志即可)以及淘汰过期的Follower。拉模式的缺点主要是处理僵尸Leader和Fetch的延迟可能较大。

领导选举

当满足以下三个条件之一时,Quorum中的某个节点就会触发选举:

  1. 向Leader发送Fetch请求后,在超时阈值quorum.fetch.timeout.ms之后仍然没有得到Fetch响应,表示Leader疑似失败;

  2. 从当前Leader收到了EndQuorumEpoch请求,表示Leader已退位;

  3. Candidate状态下,在超时阈值quorum.election.timeout.ms之后仍然没有收到多数票,也没有Candidate赢得选举,表示此次选举作废,重新进行选举。

接下来的投票流程与经典Raft协议相同,不再赘述。当然,选举过程中仍然要对无效的选票进行处理,如集群ID或纪元值过期的选票。

元数据日志复制

与维护Consumer offset的方式类似,脱离ZK之后的Kafka集群将元数据视为日志,保存在一个内置的Topic中,且该Topic只有一个Partition。

元数据日志的消息格式与普通消息没有太大不同,但必须携带Leader的纪元值(即之前的Controller epoch):

Record => Offset LeaderEpoch ControlType Key Value Timestamp

这样,Follower以拉模式复制Leader日志,就相当于以Consumer角色消费元数据Topic,符合Kafka原生的语义。

那么在KRaft协议中,是如何维护哪些元数据日志已经提交——即已经成功复制到多数的Follower节点上的呢?Kafka仍然借用了原生副本机制中的概念——high watermark(HW,高水位线)保证日志不会丢失,HW的示意图如下。

如果看官不了解HW,可以去搜索对应的资料,本文不废话了。

状态机安全性保证

在安全性方面,KRaft与传统Raft的选举安全性、领导者只追加、日志匹配和领导者完全性保证都是几乎相同的。下面只简单看看状态机安全性是如何保证的,仍然举论文中的极端栗子:

  • 在时刻a,节点S1是Leader,epoch=2的日志只复制给了S2就崩溃了;

  • 在时刻b,S5被选举为Leader,epoch=3的日志还没来得及复制,也崩溃了;

  • 在时刻c,S1又被选举为Leader,继续复制日志,将epoch=2的日志给了S3。此时该日志复制给了多数节点,但还未提交;

  • 在时刻d,S1又崩溃,并且S5重新被选举为领导者,将epoch=3的日志复制给S0~S4。

此时日志与新Leader S5的日志发生了冲突,如果按上图中d1的方式处理,消息2就会丢失。传统Raft协议的处理方式是:在Leader任期开始时,立刻提交一条空的日志,所以上图中时刻c的情况不会发生,而是如同d2一样先提交epoch=4的日志,连带提交epoch=2的日志。

与传统Raft不同,KRaft附加了一个较强的约束:当新的Leader被选举出来,但还没有成功提交属于它的epoch的日志时,不会向前推进HW。也就是说,即使上图中时刻c的情况发生了,消息2也被视为没有成功提交,所以按照d1方式处理是安全的。

背景调查时在调查些什么?

缓存之王 | Redis最佳实践&开发规范&FAQ

【大数据技术与架构】2021年大数据面试进阶系列系统总结

这篇关于脱离ZooKeeper依赖的Kafka Controller Quorum(KRaft)机制浅析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/491044

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Zookeeper安装和配置说明

一、Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式。 ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境; ■ 伪集群模式:就是在一台物理机上运行多个Zookeeper 实例; ■ 集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble) Zookeeper通过复制来实现

每天认识几个maven依赖(ActiveMQ+activemq-jaxb+activesoap+activespace+adarwin)

八、ActiveMQ 1、是什么? ActiveMQ 是一个开源的消息中间件(Message Broker),由 Apache 软件基金会开发和维护。它实现了 Java 消息服务(Java Message Service, JMS)规范,并支持多种消息传递协议,包括 AMQP、MQTT 和 OpenWire 等。 2、有什么用? 可靠性:ActiveMQ 提供了消息持久性和事务支持,确保消

搭建Kafka+zookeeper集群调度

前言 硬件环境 172.18.0.5        kafkazk1        Kafka+zookeeper                Kafka Broker集群 172.18.0.6        kafkazk2        Kafka+zookeeper                Kafka Broker集群 172.18.0.7        kafkazk3

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

【Tools】大模型中的自注意力机制

摇来摇去摇碎点点的金黄 伸手牵来一片梦的霞光 南方的小巷推开多情的门窗 年轻和我们歌唱 摇来摇去摇着温柔的阳光 轻轻托起一件梦的衣裳 古老的都市每天都改变模样                      🎵 方芳《摇太阳》 自注意力机制(Self-Attention)是一种在Transformer等大模型中经常使用的注意力机制。该机制通过对输入序列中的每个元素计算与其他元素之间的相似性,

如何通俗理解注意力机制?

1、注意力机制(Attention Mechanism)是机器学习和深度学习中一种模拟人类注意力的方法,用于提高模型在处理大量信息时的效率和效果。通俗地理解,它就像是在一堆信息中找到最重要的部分,把注意力集中在这些关键点上,从而更好地完成任务。以下是几个简单的比喻来帮助理解注意力机制: 2、寻找重点:想象一下,你在阅读一篇文章的时候,有些段落特别重要,你会特别注意这些段落,反复阅读,而对其他部分