揭开神秘的“位移主题”面纱 no.16

Kafka中神秘的内部主题(Internal Topic)__consumer_offsets。

consumer_offsets在Kafka源码中有个更为正式的名字,叫*位移主题*,即Offsets Topic。为了方便今天的讨论,我将统一使用位移主题来指代consumer_offsets。需要注意的是,它有两个下划线哦。

好了,我们开始今天的内容吧。首先,我们有必要探究一下位移主题被引入的背景及原因,即位移主题的前世今生。

在上一期中,我说过老版本Consumer的位移管理是依托于Apache ZooKeeper的,它会自动或手动地将位移数据提交到ZooKeeper中保存。当Consumer重启后,它能自动从ZooKeeper中读取位移数据,从而在上次消费截止的地方继续消费。这种设计使得Kafka Broker不需要保存位移数据,减少了Broker端需要持有的状态空间,因而有利于实现高伸缩性。

但是,ZooKeeper其实并不适用于这种高频的写操作,因此,Kafka社区自0.8.2.x版本开始,就在酝酿修改这种设计,并最终在新版本Consumer中正式推出了全新的位移管理机制,自然也包括这个新的位移主题。

新版本Consumer的位移管理机制其实也很简单,就是**将Consumer的位移数据作为一条条普通的Kafka消息,提交到**consumer_offsets中。可以这么说,**consumer_offsets的主要作用是保存Kafka消费者的位移信息。**它要求这个提交过程不仅要实现高持久性,还要支持高频的写操作。显然,Kafka的主题设计天然就满足这两个条件,因此,使用Kafka主题来保存位移这件事情,实际上就是一个水到渠成的想法了。

这里我想再次强调一下,和你创建的其他主题一样,位移主题就是普通的Kafka主题。你可以手动地创建它、修改它,甚至是删除它。只不过,它同时也是一个内部主题,大部分情况下,你其实并不需要“搭理”它,也不用花心思去管理它,把它丢给Kafka就完事了。

虽说位移主题是一个普通的Kafka主题,但它的消息格式却是Kafka自己定义的,用户不能修改,也就是说你不能随意地向这个主题写消息,因为一旦你写入的消息不满足Kafka规定的格式,那么Kafka内部无法成功解析,就会造成Broker的崩溃。事实上,Kafka Consumer有API帮你提交位移,也就是向位移主题写消息。你千万不要自己写个Producer随意向该主题发送消息。

你可能会好奇,这个主题存的到底是什么格式的消息呢?所谓的消息格式,你可以简单地理解为是一个KV对。Key和Value分别表示消息的键值和消息体,在Kafka中它们就是字节数组而已。想象一下,如果让你来设计这个主题,你觉得消息格式应该长什么样子呢?我先不说社区的设计方案,我们自己先来设计一下。

首先从Key说起。一个Kafka集群中的Consumer数量会有很多,既然这个主题保存的是Consumer的位移数据,那么消息格式中必须要有字段来标识这个位移数据是哪个Consumer的。这种数据放在哪个字段比较合适呢?显然放在Key中比较合适。

现在我们知道该主题消息的Key中应该保存标识Consumer的字段,那么,当前Kafka中什么字段能够标识Consumer呢?还记得之前我们说Consumer Group时提到的Group ID吗?没错,就是这个字段,它能够标识唯一的Consumer Group。

说到这里,我再多说几句。除了Consumer Group,Kafka还支持独立Consumer,也称Standalone Consumer。它的运行机制与Consumer Group完全不同,但是位移管理的机制却是相同的。因此,即使是Standalone Consumer,也有自己的Group ID来标识它自己,所以也适用于这套消息格式。

Okay,我们现在知道Key中保存了Group ID,但是只保存Group ID就可以了吗?别忘了,Consumer提交位移是在分区层面上进行的,即它提交的是某个或某些分区的位移,那么很显然,Key中还应该保存Consumer要提交位移的分区。

好了,我们来总结一下我们的结论。位移主题的Key中应该保存3部分内容:。如果你认同这样的结论,那么恭喜你,社区就是这么设计的!

接下来,我们再来看看消息体的设计。也许你会觉得消息体应该很简单,保存一个位移值就可以了。实际上,社区的方案要复杂得多,比如消息体还保存了位移提交的一些其他元数据,诸如时间戳和用户自定义的数据等。保存这些元数据是为了帮助Kafka执行各种各样后续的操作,比如删除过期位移消息等。但总体来说,我们还是可以简单地认为消息体就是保存了位移值。

当然了,位移主题的消息格式可不是只有这一种。事实上,它有3种消息格式。除了刚刚我们说的这种格式,还有2种格式:

  1. 用于保存Consumer Group信息的消息。
  2. 用于删除Group过期位移甚至是删除Group的消息。

第1种格式非常神秘,以至于你几乎无法在搜索引擎中搜到它的身影。不过,你只需要记住它是用来注册Consumer Group的就可以了。

第2种格式相对更加有名一些。它有个专属的名字:tombstone消息,即墓碑消息,也称delete mark。下次你在Google或百度中见到这些词,不用感到惊讶,它们指的是一个东西。这些消息只出现在源码中而不暴露给你。它的主要特点是它的消息体是null,即空消息体。

那么,何时会写入这类消息呢?一旦某个Consumer Group下的所有Consumer实例都停止了,而且它们的位移数据都已被删除时,Kafka会向位移主题的对应分区写入tombstone消息,表明要彻底删除这个Group的信息。

好了,消息格式就说这么多,下面我们来说说位移主题是怎么被创建的。通常来说,当Kafka集群中的第一个Consumer程序启动时,Kafka会自动创建位移主题。我们说过,位移主题就是普通的Kafka主题,那么它自然也有对应的分区数。但如果是Kafka自动创建的,分区数是怎么设置的呢?这就要看Broker端参数offsets.topic.num.partitions的取值了。它的默认值是50,因此Kafka会自动创建一个50分区的位移主题。如果你曾经惊讶于Kafka日志路径下冒出很多__consumer_offsets-xxx这样的目录,那么现在应该明白了吧,这就是Kafka自动帮你创建的位移主题啊。

你可能会问,除了分区数,副本数或备份因子是怎么控制的呢?答案也很简单,这就是Broker端另一个参数offsets.topic.replication.factor要做的事情了。它的默认值是3。

总结一下,如果位移主题是Kafka自动创建的,那么该主题的分区数是50,副本数是3

当然,你也可以选择手动创建位移主题,具体方法就是,在Kafka集群尚未启动任何Consumer之前,使用Kafka API创建它。手动创建的好处在于,你可以创建满足你实际场景需要的位移主题。比如很多人说50个分区对我来讲太多了,我不想要这么多分区,那么你可以自己创建它,不用理会offsets.topic.num.partitions的值。

不过我给你的建议是,还是让Kafka自动创建比较好。目前Kafka源码中有一些地方硬编码了50分区数,因此如果你自行创建了一个不同于默认分区数的位移主题,可能会碰到各种各样奇怪的问题。这是社区的一个Bug,目前代码已经修复了,但依然在审核中。

创建位移主题当然是为了用的,那么什么地方会用到位移主题呢?我们前面一直在说Kafka Consumer提交位移时会写入该主题,那Consumer是怎么提交位移的呢?目前Kafka Consumer提交位移的方式有两种:自动提交位移和手动提交位移。

Consumer端有个参数叫enable.auto.commit,如果值是true,则Consumer在后台默默地为你定期提交位移,提交间隔由一个专属的参数auto.commit.interval.ms来控制。自动提交位移有一个显著的优点,就是省事,你不用操心位移提交的事情,就能保证消息消费不会丢失。但这一点同时也是缺点。因为它太省事了,以至于丧失了很大的灵活性和可控性,你完全没法把控Consumer端的位移管理。

事实上,很多与Kafka集成的大数据框架都是禁用自动提交位移的,如Spark、Flink等。这就引出了另一种位移提交方式:手动提交位移,即设置enable.auto.commit = false。一旦设置了false,作为Consumer应用开发的你就要承担起位移提交的责任。Kafka Consumer API为你提供了位移提交的方法,如consumer.commitSync等。当调用这些方法时,Kafka会向位移主题写入相应的消息。

如果你选择的是自动提交位移,那么就可能存在一个问题:只要Consumer一直启动着,它就会无限期地向位移主题写入消息。

我们来举个极端一点的例子。假设Consumer当前消费到了某个主题的最新一条消息,位移是100,之后该主题没有任何新消息产生,故Consumer无消息可消费了,所以位移永远保持在100。由于是自动提交位移,位移主题中会不停地写入位移=100的消息。显然Kafka只需要保留这类消息中的最新一条就可以了,之前的消息都是可以删除的。这就要求Kafka必须要有针对位移主题消息特点的消息删除策略,否则这种消息会越来越多,最终撑爆整个磁盘。

Kafka是怎么删除位移主题中的过期消息的呢?答案就是Compaction。国内很多文献都将其翻译成压缩,我个人是有一点保留意见的。在英语中,压缩的专有术语是Compression,它的原理和Compaction很不相同,我更倾向于翻译成压实,或干脆采用JVM垃圾回收中的术语:整理。

不管怎么翻译,Kafka使用Compact策略来删除位移主题中的过期消息,避免该主题无限期膨胀。那么应该如何定义Compact策略中的过期呢?对于同一个Key的两条消息M1和M2,如果M1的发送时间早于M2,那么M1就是过期消息。Compact的过程就是扫描日志的所有消息,剔除那些过期的消息,然后把剩下的消息整理在一起。我在这里贴一张来自官网的图片,来说明Compact过程。

在这里插入图片描述
图中位移为0、2和3的消息的Key都是K1。Compact之后,分区只需要保存位移为3的消息,因为它是最新发送的。

Kafka提供了专门的后台线程定期地巡检待Compact的主题,看看是否存在满足条件的可删除数据。这个后台线程叫Log Cleaner。很多实际生产环境中都出现过位移主题无限膨胀占用过多磁盘空间的问题,如果你的环境中也有这个问题,我建议你去检查一下Log Cleaner线程的状态,通常都是这个线程挂掉了导致的。

小结

总结一下,今天我跟你分享了Kafka神秘的位移主题__consumer_offsets,包括引入它的契机与原因、它的作用、消息格式、写入的时机以及管理策略等,这对我们了解Kafka特别是Kafka Consumer的位移管理是大有帮助的。实际上,将很多元数据以消息的方式存入Kafka内部主题的做法越来越流行。除了Consumer位移管理,Kafka事务也是利用了这个方法,当然那是另外的一个内部主题了。

社区的想法很简单:既然Kafka天然实现了高持久性和高吞吐量,那么任何有这两个需求的子服务自然也就不必求助于外部系统,用Kafka自己实现就好了。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/844718.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3 双向绑定

需求&#xff1a;父和子实现双向数据绑定 &#xff08;Vue3.4&#xff09; 单参数实现&#xff1a; 父组件------------------<UserNamev-model:first-name"first"v-model:last-name"last" />子组件&#xff1a;------------<script setup> c…

Kotlin学习笔记 泛型

在 Kotlin 中&#xff0c;T 通常用作类型参数的占位符&#xff0c;它在实例化或传递参数时会被替换成具体的类型。 Kotlin 支持泛型&#xff0c;这意味着您可以编写可以与多种数据类型一起工作的代码&#xff0c;而不必为每种数据类型编写单独的代码。 ### 泛型类和函数 在 …

记录贴 Elasticsearch的RestClient进行DSL查询

must&#xff1a;必须匹配每个子查询&#xff0c;类似“与” should&#xff1a;选择性匹配子查询&#xff0c;类似“或” must_not&#xff1a;必须不匹配&#xff0c;不参与算分&#xff0c;类似“非” filter&#xff1a;必须匹配&#xff0c;不参与算分 import cn.huto…

Kali 我来了

Kali 我来了 1、官网下载2、修改密码3、开启SSH远程登录服务4、关闭kali图形化界面 1、官网下载 官方链接: https://www.kali.org/ 下载链接: https://cdimage.kali.org/kali-2024.1/kali-linux-2024.1-vmware-amd64.7z 解压后 直接导入 VmWare 就可使用可爱的小 Kali 了。 …

AOP——学习

AOP&#xff08;面向切面编程&#xff09;是Spring框架的重要特性之一&#xff0c;用于分离关注点并处理横切关注点&#xff0c;如日志记录、安全性和事务管理。在面试中&#xff0c;AOP相关的问题通常会涉及基本概念、应用场景、实际使用、以及与其他编程范式的比较。以下是一…

LabVIEW机器设备的振动监测

振动监测是工业和机械维护中重要的一部分&#xff0c;通过检测和分析机械振动&#xff0c;提前发现潜在故障&#xff0c;确保设备的可靠运行。LabVIEW是一种强大的图形化编程环境&#xff0c;非常适合用于振动监测系统的开发和实施。以下从多个角度详细介绍LabVIEW在振动监测中…

互联网应用主流框架整合之数据库编程

Spring最重要的功能就是操作数据&#xff0c;数据库编程也是互联网编程的基础&#xff0c;Spring为开发者提供了JDBC模板模式&#xff0c;使用JdbcTemplate可以简化许多编码工作&#xff0c;同时也提供了TransactionTemplate支持事务的模板&#xff0c;但都不是常用技术&#x…

管理能力学习笔记十一:如何通过反馈做好辅导

关于辅导的常见错误 辅导过于细致 辅导的首要障碍: 不相信对方的潜力需要有成长型思维&#xff1a;即便员工现在不OK&#xff0c;未来会更好因材施教&#xff1a;对不同风格的下属&#xff0c;采取不同的辅导风格 凡事亲力亲为 作为管理者&#xff0c;我们要做的是&#xf…

【Unity2D 2022:Particle System】添加粒子特效

一、创建粒子系统游戏物体 1. 创建粒子系统游戏物体Smog Effect 2. 给粒子特效添加精灵贴图 &#xff08;1&#xff09;启用Texture Sheet Animation&#xff08;纹理表动画&#xff09; &#xff08;2&#xff09;点击加号添加一个纹理&#xff0c;并将两张厌恶图片导入到纹理…

【YashanDB知识库】OCI驱动类问题定位方法

【标题】OCI驱动类问题定位方法 【需求分类】故障分析 【关键字】OCI 【需求描述】由于我们的OCI接口目前尚不完善&#xff0c;经常会遇见OCI接口能力不足导致应用功能无法运行的问题&#xff0c;需要定位手段确定底层是哪个接口报错 【需求原因分析】方便一线数据库管理员…

使用jdk自带jhat工具排查OOM问题

使用jdk自带jhat工具排查OOM问题 OOM java.lang.OutOfMemoryError: Java heap space排查步骤 编写一个测试类 public class TestJVM {Testpublic void test1() throws InstantiationException, IllegalAccessException {List<A> list new ArrayList<>();for (i…

做抖音小店什么类目最容易爆单?搞懂这三点就明白了!

大家好&#xff0c;我是电商糖果 我们刚接触电商的时候&#xff0c;一定经常听一些同行念叨&#xff0c;选择大于努力&#xff0c;类目大于一切。 很多电商人把选类目比做定生死。 类目选对了&#xff0c;让你轻松飞升不是问题&#xff0c;类目选错了&#xff0c;基本被判了…

【YOLOv10】使用yolov10训练自己的数据集/验证 /推理 /导出模型/ONNX模型的使用

YOLOv10: 实时端到端的目标检测。 性能 YOLOv10比最先进的YOLOv9延迟时间更低&#xff0c;测试结果可以与YOLOv9媲美&#xff0c;可能会成为YOLO系列模型部署的“新选择”。 目录 1 数据准备 2 配置文件 3 训练 4 验证 5 预测 6 导出模型 7 ONNX模型的使用 官方论文地址…

从源头治理:数据提取阶段的数据安全控制与合规性设计

在数字化转型加速推进的今天&#xff0c;数据已成为企业的核心资产之一。然而&#xff0c;随着数据量的激增和数据来源的多样化&#xff0c;数据提取过程中的安全与合规问题日益凸显&#xff0c;成为企业不可忽视的风险点。本文将探讨如何在数据提取阶段实施有效的数据安全控制…

学习笔记——动态路由协议——OSPF(OSPF网络类型1)

五、OSPF网络类型 网络类型&#xff1a;是指运行OSPF网段的二层链路类型。 1、OSPF网络类型简介 (1) OSPF网络类型 MA(Multi-Access &#xff0c;多路访问)在一个网段内的节点数量不限制(一条链路上有多个访问点)。MA的网络一般分为两种&#xff1a; 1)广播式多路访问网络…

oracle数据库无法连接问题排查

查看数据库告警日志如下图。发现问题时间段&#xff0c;没有数据库服务故障报错&#xff0c;但是存在较多TNS-12535、12560、12170、00505错误&#xff1a; 通过检查问题时间段应用日志&#xff0c;也记录了Caused by:java.sql.SQLRecoverableException: IO 错误: Connection r…

音乐传奇告别之作:《杰作》未解之谜❗❗

坂本龙一的《杰作》不仅是一部音乐会纪录电影&#xff0c;更是他赠予世界的一封深情告别信。 这部影片精心收录了这位音乐巨匠生前最后一场钢琴独奏音乐会的珍贵瞬间&#xff0c; 其中涵盖了《圣诞快乐&#xff0c;劳伦斯先生》、《末代皇帝》、《水》等二十首令人陶醉的经典…

c++常用设计模式

1、单例模式(Singleton)&#xff1a;保证一个类只有一个实例&#xff0c;提供一个全局访问点&#xff1b; class Singleton { private:static Singleton* instance;Singleton() {}public:static Singleton* getInstance() {if (instance nullptr) {instance new Singleton()…

分布式事务-TCC

分布式事务TCC是一种补偿式的分布式事务解决方案&#xff0c;旨在保证在分布式系统中&#xff0c;跨多个服务或资源的事务能够保持一致性和可靠性。 一、TCC概述 TCC&#xff0c;全称Try-Confirm-Cancel&#xff0c;是一种用于处理分布式事务的协议。其核心思想是通过在业务逻…

誉天Linux云计算架构师就业班要学习哪些内容?

课程设计思路&#xff1a; 根据十多年来毕业学员的就业和反馈&#xff0c;对数百名学员的就业回访;Linux运维&#xff0c;云计算&#xff0c;高并发&#xff0c;分布式&#xff0c;容器&#xff0c;云原生&#xff0c;自动化等是目前市场上就业情况最好&#xff0c;需求量最大&…