Kafka实践:到底该不该把不同类型的消息放在同一个主题中?

Kafka多个消费者监听消费同一个Topic主题 多个消费者监听消费同一个Topic主题一、需求介绍1.图解2.关键注解@kafkaListener二、代码实现1)第一个消费者2)第二个消费者3)生产者三、测试 一、需求介绍 有一个Topic:hw_data 有3个分区 3个副本 组:hw-data-group 将这个主题的消息分发给两个(或者多个)消费者消费,(不能消费相同的消息) 1.图解 2.关键注解@kafkaListener @Target({ ElementType.TYPE, ElementType.METHOD, ElementTyp 阅读详情

Kafka 主题最重要的一个功能是可以让消费者指定它们想要消费的消息子集。在极端情况下,将所有数据放在同一个主题中可能不是一个好主意,因为这样消费者就无法选择它们感兴趣的事件——它们需要消费所有的消息。另一种极端情况,拥有数百万个不同的主题也不是一个好主意,因为 Kafka 的每个主题都是有成本的,拥有大量主题会损害性能。

实际上,从性能的角度来看,分区数量才是关键因素。在 Kafka 中,每个主题至少对应一个分区,如果你有 n 个主题,至少会有 n 个分区。不久之前,Jun Rao 写了一篇博文,解释了拥有多个分区的成本(端到端延迟、文件描述符、内存开销、发生故障后的恢复时间)。根据经验,如果你关心延迟,那么每个节点分配几百个分区就可以了。如果每个节点的分区数量超过成千上万个,就会造成较大的延迟。

关于性能的讨论为设计主题结构提供了一些指导:如果你发现自己有数千个主题,那么将一些细粒度、低吞吐量的主题合并到粗粒度主题中可能是个明智之举,这样可以避免分区数量蔓延。

然而,性能并不是我们唯一关心的问题。在我看来,更重要的是主题结构的数据完整性和数据模型。我们将在本文的其余部分讨论这些内容。

主题等于相同类型事件的集合?

人们普遍认为应该将相同类型的事件放在同一主题中,不同的事件类型应该使用不同的主题。这种思路让我们联想到关系型数据库,其中表是相同类型记录的集合,于是我们就有了数据库表和 Kafka 主题之间的类比。

Confluent Avro Schema Registry 进一步强化了这种概念,因为它鼓励你对主题的所有消息使用相同的 Avro 模式(schema)。模式可以在保持兼容性的同时进行演化(例如通过添加可选字段),但所有消息都必须符合某种记录类型。稍后我会再回过头来讨论这个问题。

对于某些类型的流式数据,例如活动事件,要求同一主题中所有消息都符合相同的模式,这是合理的。但是,有些人把 Kafka 当成了数据库来用,例如事件溯源,或者在微服务之间交换数据。对于这种情况,我认为是否将主题定义为具有相同模式的消息集合就不那么重要了。这个时候,更重要的是主题分区中的消息必须是有序的。

想象一下这样的场景:你有一个实体(比如客户),这个实体可能会发生许多不同的事情,比如创建客户、客户更改地址、客户向帐户中添加新的信用卡、客户发起客服请求,客户支付账单、客户关闭帐户。

这些事件之间的顺序很重要。例如,我们希望其他事件必须在创建客户之后才能发生,并且在客户关闭帐户之后不能再发生其他事件。在使用 Kafka 时,你可以将它们全部放在同一个主题分区中来保持它们的顺序。在这个示例中,你可以使用客户 ID 作为分区的键,然后将所有事件放在同一个主题中。它们必须位于同一主题中,因为不同的主题对应不同的分区,而 Kafka 是不保证分区之间的顺序的。

顺序问题

如果你为 customerCreated、customerAddressChanged 和 customerInvoicePaid 事件使用了不同的主题,那么这些主题的消费者可能就看不到这些事件之间的顺序。例如,消费者可能会看到一个不存在的客户做出的地址变更(这个客户尚未创建,因为相应的 customerCreated 事件可能发生了延迟)。

如果消费者暂停一段时间(比如进行维护或部署新版本),那么事件出现乱序的可能性就更高了。在消费者停止期间,事件继续发布,并且这些事件被存储在特定定的主题分区中。当消费者再次启动时,它会消费所有积压在分区中的事件。如果消费者只消费一个分区,那就没问题:积压的事件会按照它们存储的顺序依次被处理。但是,如果消费者同时消费几个主题,就会按任意顺序读取主题中数据。它可以先读取积压在一个主题上的所有数据,然后再读取另一个主题上积压的数据,或者交错地读取多个主题的数据。

因此,如果你将 customerCreated、customerAddressChanged 和 customerInvoicePaid 事件放在三个单独的主题中,那么消费者可能会在看到 customerCreated 事件之前先看到 customerAddressChanged 事件。因此,消费者很可能会看到一个客户的 customerAddressChanged 事件,但这个客户却未被创建。

你可能会想到为每条消息附加时间戳,并用它来对事件进行排序。如果你将事件导入数据仓库,再对事件进行排序,或许是没有问题的。但在流数据中只使用时间戳是不够的:在你收到一个具有特定时间戳的事件时,你不知道是否需要等待具有较早时间戳的事件,或者所有之前的事件是否已经在当前事情之前到达。依靠时钟进行同步通常会导致噩梦,有关时钟问题的更多详细信息,请参阅“Designing Data-Intensive Applications”的第 8 章。

何时拆分主题,何时合并主题?

基于这个背景,我将给出一些经验之谈,帮你确定哪些数据应该放在同一主题中,以及哪些数据应该放在不同的主题中。

首先,需要保持固定顺序的事件必须放在同一主题中(并且需要使用相同的分区键)。如果事件属于同一实体,那么事件的顺序就很重要。因此,我们可以说,同一实体的所有事件都应该保存在同一主题中。
如果你使用事件溯源进行数据建模,事件的排序尤为重要。聚合对象的状态是通过以特定的顺序重放事件日志而得出的。因此,即使可能存在不同的事件类型,聚合所需要的所有事件也必须在同一主题中。
对于不同实体的事件,它们应该保存在相同的主题中还是不同的主题中?我想说,如果一个实体依赖于另一个实体(例如一个地址属于一个客户),或者经常需要同时用到它们,那么它们也应该保存在同一主题中。另一方面,如果它们不相关,并且属于不同的团队,那么最好将它们放在不同的主题中。
另外,这也取决于事件的吞吐量:如果一个实体类型的事件吞吐量比其他实体要高很多,那么最好将它分成几个主题,以免让只想消费低吞吐量实体的消费者不堪重负(参见第 4 点)。不过,可以将多个具有低吞吐量的实体合并起来。
如果一个事件涉及多个实体该怎么办?例如,订单涉及到产品和客户,转账至少涉及到两个账户。
我建议在一开始将这些事件记录为单个原子消息,而不是将其分成几个属于不同主题的消息。在记录事件时,最好可以保持原封不动,即尽可能保持数据的原始形式。你可以随后使用流式处理器来拆分复合事件,但如果过早进行拆分,想要重建原始事件会难得多。如果能够为初始事件分配一个唯一 ID(例如 UUID)就更好了,之后如果你要拆分原始事件,可以带上这个 ID,从而可以追溯到每个事件的起源。
看看消费者需要订阅的主题数量。如果几个消费者都订阅了一组特定的主题,这表明可能需要将这些主题合并在一起。
如果将细粒度的主题合并成粗粒度的主题,一些消费者可能会收到他们不需要的事件,需要将其忽略。这不是什么大问题:消费消息的成本非常低,即使最终忽略了一大半的事件,总的成本可能也不会很大。只有当消费者需要忽略绝大多数消息(例如 99.9%是不需要的)时,我才建议将大容量事件流拆分成小容量事件流。
用作 Kafka Streams 状态存储(KTable)的变更日志主题应该与其他主题分开。在这种情况下,这些主题由 Kafka Streams 流程来管理,所以不应该包含其他类型的事件。
最后,如果基于上述的规则依然无法做出正确的判断,该怎么办?那么就按照类型对事件进行分组,把相同类型的事件放在同一个主题中。不过,我认为这条规则是最不重要的。
模式管理

如果你的数据是普通文本(如 JSON),而且没有使用静态的模式,那么就可以轻松地将不同类型的事件放在同一个主题中。但是,如果你使用了模式编码(如 Avro),那么在单个主题中保存多种类型的事件则需要考虑更多的事情。

如上所述,基于 Avro 的 Kafka Confluent Schema Registry 假设了一个前提,即每个主题都有一个模式(更确切地说,一个模式用于消息的键,一个模式用于消息的值)。你可以注册新版本的模式,注册表会检查模式是否向前和向后兼容。这样设计的一个好处是,你可以让不同的生产者和消费者同时使用不同版本的模式,并且仍然保持彼此的兼容性。

Confluent 的 Avro 序列化器通过 subject 名称在注册表中注册模式。默认情况下,消息键的 subject 为-key,消息值的 subject 为-value。模式注册表会检查在特定 subject 下注册的所有模式的相互兼容性。

最近,我为 Avro 序列化器提供了一个补丁(https://github.com/confluentinc/schema-registry/pull/680 ),让兼容性检查变得更加灵活。这个补丁添加了两个新的配置选项:key.subject.name.strategy(用于定义如何构造消息键的 subject 名称)和 value.subject.name.strategy(用于定义如何构造消息值的 subject 名称)。它们的值可以是如下几个:

io.confluent.kafka.serializers.subject.TopicNameStrategy(默认):消息键的 subject 名称为-key,消息值为-value。这意味着主题中所有消息的模式必须相互兼容。
io.confluent.kafka.serializers.subject.RecordNameStrategy:subject 名称是 Avro 记录类型的完全限定名。因此,模式注册表会检查特定记录类型的兼容性,而不管是哪个主题。这个设置允许同一主题包含不同类型的事件。
io.confluent.kafka.serializers.subject.TopicRecordNameStrategy:subject 名称是-,其中是 Kafka 主题名,是 Avro 记录类型的完全限定名。这个设置允许同一主题包含不同类型的事件,并进一步对当前主题进行兼容性检查。
有了这个新特性,你就可以轻松地将属于特定实体的所有不同类型的事件放在同一个主题中。现在,你可以自由选择主题的粒度,而不仅限于一个类型对应一个主题。

喜欢小编轻轻点关注哦!

使用@KafkaListener配置两个不同的Consumer监听不同kafka集群的消息 我们的项目中很多系统交互使用的kafka,最近遇到一个问题,原来我们的kafka需要监听消费我们自己的kafka生产的消息,但是现在需要使用kafka来消费外部系统的消息,但是我们原来的使用非常简单,直接在application.yml中进行的配置,同时监听两个kafka的话,不能实现,于是就要解决这个问题啦。 下面是我们之前的配置方式: yml文件中的配置: 消费者配置: ... 阅读详情

相关推荐

kafka中的消息(topic)和日志(log)

目录 一、消息和日志的关系 二、查看Kafka主题(Topic)情况 三、查看Kafka数据存储(Log)情况 一、消息和日志的关系 可以理解Topic是一个类别的名称,同类消息发送到同一个Topic下面。对于每一个Topic,下面可以有多个分区(Partition)日志文件: Partition是一个有序的message序列(消息队列),这些message按顺序添加到一个叫做commit log的文件中。每个partition中的消息都有一个唯一的编号,称之为offset,用来唯一标示某个

swadian2008的博客 1万+

Kafka-Topic管理、API使用

Kafka-Topic管理、API使用Kafka环境搭建APIOffset自动控制Acks & RetriesRetries幂等性保证事务控制Topic管理 Kafka 环境搭建       1.安装JDK,配置JAVA_HOME       2.配置主机名和IP映射       3.关闭防火墙&防火墙开机自启动

weixin_49442658的博客 471

华为[ENSP]—— 实验二、三层交换和ARP的工作原理

华为[ENSP]三层交换和ARP的工作原理

weixin_62594100的博客 6412

kafka复习整理(1)

1)Producer :消息生产者,就是向kafka broker发消息的客户端; 2)Consumer :消息消费者,向kafka broker取消息的客户端; 3)Consumer Group (CG):消费者组,由多个consumer组成。消费者组内每个消费者负责消费不同分区的数据,同一个topic的一个分区只能由同一个组内消费者消费;消费者组之间互不影响。所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。比如组长 组员 大家共同干一件事,每个人干一件事,干了什么是由kafka记录组长也

weixin_43805212的博客 354

从 0 到 1 构建 Graph RAG 系统:本地图谱 + 通义千问落地实践

本文介绍了一个基于知识图谱的检索增强生成系统(Graph RAG),该系统结合领域知识图谱、语义检索和大模型问答,旨在提供结构化、精准的技术问答服务。文章详细说明了项目背景、目标、核心技术架构以及实现方法,包括本地图谱构建、Neo4j数据库接入、语义检索和大模型集成等关键环节。该系统支持混合检索、多轮问答和知识图谱关联理解,能够有效减少大模型幻觉,提升问答的准确性和可解释性。文中还展示了核心代码结构和流程图,呈现了从文档加载到图谱构建再到问答生成的完整流程。该系统适用于需要处理复杂领域知识的研发和数据分析场

m0_58378112的博客 1402

深度学习-算法工程师岗位面试常见问题及解答

一、相关的问题 深度学习优化学习方法(一阶、二阶) 一阶方法:随机梯度下降(SGD)、动量(Momentum)、牛顿动量法(Nesterov动量)、AdaGrad(自适应梯度)、RMSProp(均方差传播)、Adam、Nadam。 二阶方法:牛顿法、拟牛顿法、共轭梯度法(CG)、BFGS、L-BFGS。 自适应优化算法有哪些?(Adagrad(累积梯度平方)、RMSProp(累积梯度平方的滑动平均)、Adam(带动量的RMSProp,即同时使用梯度的一、二阶矩))。 梯度下降陷入局部最优有什么解决

nobles007820的博客 2924

Kafka实践:到底该不该把不同类型的消息放在同一个主题中

如果你使用了像Kafka这样的流式处理平台,就要搞清楚一件事情:你需要用到哪些主题?特别是如果你要将一堆不同的事件作为消息发布到Kafka,是将它们放在同一个主题中,还是将它们拆分到不同的主题中?\\Kafka主题最重要的一个功能是可以让消费者指定它们想要消费的消息子集。在极端情况下,将所有数据放在同一个主题中可能不是一个好主意,因为这样消费者就无法选择它们感兴趣的事件——它们需要消费所有的消息。...

cpongo5 340

AI人工智能领域多模态大模型的数字孪生应用

本文旨在系统性地介绍多模态大模型在数字孪生领域的最新应用进展,探讨其技术原理、实现方法和应用价值。内容范围涵盖从基础概念到前沿技术,从理论分析到实践案例。文章首先介绍多模态大模型和数字孪生的基本概念,然后深入分析两者的结合点,接着通过具体案例展示应用实践,最后探讨未来发展趋势和挑战。多模态大模型:能够同时处理和融合多种数据模态(如文本、图像、视频、音频等)的大型人工智能模型数字孪生:物理实体或系统的虚拟副本,通过实时数据同步实现虚实交互跨模态融合:将不同数据模态的信息进行有效整合和关联的技术。

AI云原生与云计算技术学院 1325

应该在同一个Kafka主题中放入几种事件类型吗?

  使用此新功能,可以轻松,干净地将特定事物的所有不同事件放在同一主题中。现在,可以根据上述条件自由选择主题的粒度,而不仅限于每个主题的单个事件类型。

zouduchen的博客 263

Google OR-Tools的CP-SAT求解器,为什么比传统线性规划更适合你的组合优化问题?

本文深入解析Google OR-Tools中的CP-SAT求解器为何比传统线性规划更适合解决组合优化问题。CP-SAT融合约束规划与可满足性理论,原生支持复杂逻辑约束和离散决策,在物流、生产调度等领域展现出显著优势。通过技术对比和实战案例,展示CP-SAT在处理高组合复杂度问题时的卓越性能。

weixin_28700593的博客 927

AndroidKiller之APK 编译失败,无法继续下一步签名【BUG解决】【App反向解析】

文章目录项目场景:问题描述原因分析:解决方案:BUG解决 项目场景: AndroidKiller: 在反向解析APP包时报错:APK 编译失败,无法继续下一步签名。 网上很多方法都是无效的哈,我追究原因发现,这个bug的出现大部分情况都是因为Apktool的问题。 此方法:百分之百解决此bug! 错误如下: 问题描述 APK 编译失败,无法继续下一步签名! 原因分析: Apktool版本不适配的问题,现在的技术更新换代太快,我们安装AndroidKiller的时候,有时候不是官方渠道的话,他的版本是非常

一键难忘的博客 2万+

电脑卡顿怎么办?系统综合管理软件原理与使用风险详解

电脑使用一两年后,开机变慢、C盘飘红、软件响应卡顿是常见现象。很多人依赖系统优化工具一键清理,却又担心注册表清理带来风险。实际上,理解系统维护的基础原理比盲目操作更重要。日常卡顿多源于启动项过多、临时文件积累、磁盘空间不足或机械硬盘碎片化。系统综合管理工具的价值在于将这些分散的维护动作集中化,降低操作门槛,但“维护”与“优化”必须分清:清理临时文件、管理启动项是安全维护,而修改服务、深度清理注册表则属于高风险操作。磁盘碎片整理和卸载残留扫描也需要结合硬盘类型与软件使用场景理性判断。本文围绕八大类40+工具,

weixin_33937778的博客 476

YOLOv12涨点优化:自研检测头 | 独家创新(Partial_C_v12Detect)检测头结构创新,实现涨点

现有12Detect进行二次创新,提升检测精度,独家创新(Partial_C_12Detect)检测头结构创新,适合科研创新度十足,强烈推荐

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 633

kafka是单独的进城吗_Kafka实践:到底该不该把不同类型的消息放在同一个主题中?...

Kafka 主题最重要的一个功能是可以让消费者指定它们想要消费的消息子集。在极端情况下,将所有数据放在同一个主题中可能不是一个好主意,因为这样消费者就无法选择它们感兴趣的事件——它们需要消费所有的消息。另一种极端情况,拥有数百万个不同的主题也不是一个好主意,因为 Kafka 的每个主题都是有成本的,拥有大量主题会损害性能。实际上,从性能的角度来看,分区数量才是关键因素。在 Kafka 中,每个主题...

weixin_39706491的博客 124

深入剖析 Wenet 下 AISHELL-1 的 run.sh 脚本:从数据准备到模型训练

run.sh脚本用于处理 AISHELL-1 数据集的整个训练和测试流程。我们将逐步分析脚本中的每个部分,包括环境变量、参数设置、各个阶段的执行等。stage: 设置脚本的起始阶段(如数据准备)。stop_stage: 设置脚本的结束阶段。通过对 Wenet 下 AISHELL-1 的run.sh脚本的详细剖析,我们希望你能更好地理解每个步骤的功能及其背后的原理。此脚本不仅为模型训练提供了便利,也为用户自定义和扩展训练流程提供了基础。希望本教程能帮助你顺利完成语音识别项目!

帅小柏的博客 1634

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【Kafka专栏 05】一条消息的完整生命周期:Kafka如何保证消息的顺序消费

除了默认的哈希分区策略外,Kafka还允许使用自定义的分区器。这为用户提供了更大的灵活性,可以根据业务需求自定义分区逻辑,进一步确保消息的顺序性。Kafka通过其独特的分区机制、消费者组配置、生产者的分区策略以及监控与错误处理机制,共同保证了消息的顺序消费。在实际应用中,需要根据业务需求合理配置和使用这些机制,以确保消息的有序性。同时,也需要注意Kafka的性能和可扩展性,以满足大规模数据处理的需求。

weixin_40736233的博客 2789

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Kafka查询topic以及消息内容

基于kafka_2.11-0.10.0.1版本: 查看kafka的安装目录 find / -name kafka* -type d 查看redis安装目录: ps -ef|grep redis 查询所有group信息: ./bin/kafka-topics.sh --list --zookeeper localhost:2181 创建topic:paymentmgt_download_asyn_deal ./bin/kafka-topics.sh --create --zookeep

MieMieFly的专栏 9万+

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

聊聊 Kafka:Kafka 消息重复的场景以及最佳实践

一、前言 上一篇我们讲了 聊聊 Kafka:Kafka 消息丢失的场景以及最佳实践,这一篇我们来说一说 Kafka 消息重复的场景以及最佳实践。 我们下面会从以下两个方面来说一下 Kafka 消息重复的场景以及最佳实践。 生产者重复消息 消费者重复消息 二、Kafka 消息重复的场景 2.1 生产者重复消息 2.1.1 根本原因 生产者发送的消息没有收到 Broker 正确的响应,导致生产者重试。 生产者发出一条消息,Broker 落盘以后因为网络等种种原因,发送端得到一个发送失败的响应或者网 络中断,

riemann_的博客 4025

Kafka发送消费消息

3.发送消息把消息发送给broker中的某个topic我们可以直接在命令行中输入内容,将消息发送到Kafka中,每一行会被当做一个独立的消息;使用kafka的发送消息客户端——>发送到指定的kafka服务器地址和topic主题就是日志文件下:主题-标识id分区下的0000.log上面也讲了消息的发送者将消息发送到oooo.log中,并且按照偏移量排序,所以消费者去当中进行消费本质就是一个发布订阅,我们来看看日志文件看看是如何消费的。

weixin_57128596的博客 5009
上一篇: 为什么已有Kafka,我们最终却选择了Apache Pulsar?
下一篇: 基于redis和zookeeper的分布式锁实现方式
java1856905
博客等级 码龄8年 100粉丝 249原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值