Apache Kafka 101 - 简介

2025-06-07

Apache Kafka 101 - 简介

免责声明:本文旨在总结我对 Kafka 的一些理解,并分享出来供大家参考。我并非 Kafka 专家,如果文中有任何错误,请留言,以便我修改。任何有助于改进本文的建议都欢迎提出。好了,让我们开始旅程吧 :)

同步与异步通信

在深入研究 Kafka 之前,我们先来简单了解一下同步和异步通信的概念,方便那些没听说过 Kafka 的朋友理解。如果你知道它们的区别,可以直接跳过这部分

首先,我们来看一个同步通信的例子:一个客户端应用向 REST API 服务发送 HTTP 请求。在这种情况下,客户端通过 HTTP 协议与服务器建立连接,并发送一些数据,服务器将接收并处理这些数据,然后将结果返回给客户端。如果客户端在预期时间内未收到响应,则会抛出错误(也就是我们熟知的超时)。这种架构非常简单,通常适用于大多数客户端需要与服务器通信的情况。

但是,想象一下,你在一家电子商务公司工作,并且需要实现网站的购买按钮。常规的同步请求足以处理这种情况吗?

如果客户点击购买,你可能需要检查仓库是否有库存、用户的信用卡是否有效、收货地址是否存在等等,但最终还是需要向客户发出购买成功完成的响应。即使你告诉了用户,购买过程也不会就此结束。物流需要将所有购买的商品分开并组装成包裹,快递公司会取货,并且随着进度的变化,一些跟踪信息会发送给用户。这些操作本质上是异步的。用户无需等待所有这些操作完成才知道购买已完成。否则,网上购物将会非常麻烦。

异步通信正是为此而生。通过异步通信,您可以将电子邮件、物流集成、追踪等不需要立即处理的事情留到以后处理,确保用户尽快收到购买反馈。

通过消息传递系统,我们使发送者和接收者能够进行通信,而无需双方必须同时监听消息。如下图所示,发送者可以生成消息,只要接收者可用,它就会读取并处理该消息。

消息传递

在上述场景中,想象一下,您无需向每个系统发送 REST API 调用来通知订单已下达,而是只需向队列发送一条消息,说“嘿,有人下了一个订单,这是您可能感兴趣的信息”。或者,甚至可以说“嘿,那个包裹的追踪位置发生了变化,您可能需要处理一下”。

如果所有依赖此事件的服务都能在它们可用时执行任何它们需要的操作(甚至可能发送后续消息),那该有多好啊!您的电子邮件服务会非常乐意在所有依赖项可用时平静地阅读此消息并将更新发送给用户,不是吗?这就是我们希望通过异步通信实现的目标。

那么,这个Kafka怎么样

什么是 Kafka?

Apache Kafka是一个分布式流式传输平台,具有高弹性和容错能力。

您可以使用 Kafka 实现许多用例,其使用示例包括:

  • 消息传递
  • 日志收集
  • 流处理
  • ETC。

在本文中,我们将概述一些 Kafka 核心概念,以便您了解它的主要功能,重点是使用它进行消息传递和分布式系统通信。

  • 主题
  • 分区
  • 经纪人
  • 生产者
  • 消费者
  • 消费者群体

通过所有这些概念,Kafka 的主张是提供一种能够实现水平可扩展性和高性能的结构。

核心概念

主题

主题 (Topic) 是你的消息将被发送到(生产)的地方。任何想要读取这条信息的人都会从主题中读取(消费)。
在 Kafka 中,你可以拥有任意数量的主题,每个主题包含给定数量的分区(由你在创建主题时定义)。因此,每当向主题生产一条消息时,它都会被写入主题的给定分区中,除非提供密钥,否则分区是随机选择的。

主题和分区
(图片来自 Kafka文档

在主题中,数据会保留一段时间。默认值为 7 天,但可以延长。有些情况下,这些消息会在主题中保留一年。这里需要注意的是,一旦消息写入给定分区,您将无法再对其进行更改。能够将数据存储如此长的时间,让您能够在必要时重新处理消息,这正是 Kafka 可靠的关键所在。在看到一些生产环境中的用例后,我可以肯定地说,这在某些情况下会起到至关重要的作用。

分区

在每个分区中,消息将被排序,并在 Kafka 中接收一个增量 ID,称为偏移量 (offset)。消费者基本上指向它读取的最后一个偏移量,每当有新消息被消费时,该指针就会向前移动到下一条消息。这个过程是一个offset commit,并且始终是增量的。

分区和偏移
(图片来自 Kafka文档

经纪人

使用 Kafka 时,您将拥有一个 Kafka 集群作为基础架构。这个集群本质上是由一堆服务器组成的,在我们的例子中,它们就是代理服务器。那么,这个代理服务器是用来做什么的呢?

还记得我们说过一个主题由多个分区组成吗?为了提高弹性并处理服务器故障,每个 Broker 都会包含一个特定的主题分区。

连接到 Broker(引导服务器)时,您将连接到整个集群。每个 Kafka Broker 本身就是一个引导服务器,它了解所有 Broker、主题和分区。当 Kafka 客户端连接到 Broker 时,它将收到所有 Broker 的列表,并最终根据需要连接到其中一个 Broker。Broker 通过 ID 进行标识。

假设一个集群包含 3 个 Broker 和一个主题(称为 A)。为了实现消息传递的弹性,我们需要一些信息副本,对吗?以防万一某个服务器出现问题。

这在 Kafka 中被称为replication factor,主题应该具有复制因子 > 1,通常在 2 到 3 之间。

经纪人

在这个例子中,我们的复制因子为 2,因此每个分区存在于 2 个 Broker 中。所以,即使一个 Broker 不可用,您仍然可以从另一个 Broker 读取该分区。但是,如果复制因子为 3,即使丢失两个 Broker,我们也能承受,并且仍然可以在一个 Broker 中使用这三个分区。

复制如何工作?

在任何给定时间点,一个(且只有一个)broker可以成为给定分区的leader。其他分区称为In Sync ReplicasISR(独立主从)。写入主题时,只有leader可以为分区提供数据,其他broker需要同步数据。

压缩

您可以在 Broker 配置中启用数据压缩来减小消息大小,更多信息请参见此处。搜索compression.type

生产者

为了能够使用 Kafka,我们需要能够读取和写入我们喜欢的主题的消息,不是吗?因此,我们需要一个实现这一点的API 。

生产者负责将数据写入主题(记住,这些数据实际上会被写入分区)。如果要概括生产者的含义,那就差不多了。然而,如果 API 中只有生产者,那么它的弹性就不够强。

为此,生产者能够检测到代理中的故障,并从该代理恢复到其他代理。如前所述,也可以在消息中发送键以启用排序。如果没有键,数据将按循环选择发送到某个分区。但是,如果有键,则会根据该键生成一个哈希值,并且该键将始终发送到该哈希值的分区。

这是为了确保消息的有序性。需要注意的是,分区数量不能改变,否则哈希机制会发生变化,最终导致无法保证消息的有序性。

致谢

可以选择在生成消息时接收确认。

确认值 结果
0 无需确认
1 等待领导者确认
全部 Leader + 副本必须确认

值得一提的是,Kafka 可以配置重试,包括退避配置和超时。但请注意,如果您配置了重试,Kafka 可能会乱序发送消息,请务必注意。

另外,您还可以实现幂等生产者:

[...] 幂等生产者增强了 Kafka 的交付语义,从至少一次交付变为恰好一次交付。特别是生产者重试将不再引入重复。[...]

阅读更多内容

消费者

现在我们到了从给定主题读取消息的阶段。消费者知道从哪个 Broker 读取消息,并且每个消费者都会从给定的分区(或者多个分区,稍后会详细介绍)读取消息。通过避免同一分区中存在多个消费者,Kafka 可以确保同一消息不会被两个消费者同时处理。以下是API供参考。

消费者
(图片来自 Kafka文档

消费者群体

消费者与一个消费者组绑定。如上图所示,每个服务器包含分区(P#,其中 # 是分区号),每个消费者都属于一个特定的消费者组。消费者组 A 中的每个消费者从两个主题读取数据,而消费者组 B 中的每个消费者只从单个分区读取数据。当每个消费者从单个分区读取数据,并且您发送带有键的消息时,可以确保消费者按顺序从其读取的分区读取消息。需要注意的是,如果您的消费者数量多于分区数量,则某些消费者将处于非活跃状态。

偏移量

消费者偏移量是针对特定消费者组的,提交后会被 Kafka 存储。此提交发生在消费者收到数据并处理完毕时。

消费者选择何时提交这些偏移量。有三种类型可供选择:

送货 影响
最多一次 一旦收到消息,偏移量就会被提交。进程失败意味着消息丢失。
至少一次 处理消息时提交偏移量
恰好一次 我将在这里留下一篇来自 Confluence 的博客文章,因为它有点复杂。

需要注意的一点是,使用at least once配置时,您可能会多次阅读该消息,因此请做好准备。

图书馆

过去一年我一直在使用 Node;因此,我们使用的库是KafkaJS。这是一个开源库,拥有一些非常优秀的功能,而且很容易上手。如果你想从基础开始学习,不妨看看!:)

另外,按照此文档操作,您就可以在本地运行 Kafka(使用 Docker)并开心地运行它 :)

参考

https://kafka.apache.org/intro
https://kafka.apache.org/documentation/
https://kafka.apache.org/24/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html
https://kafka.apache.org/24/javadoc/index.html?org/apache/kafka/clients/consumer/KafkaConsumer.html

JS 库https ://kafka.js.org/docs/getting-started

赞赏

  • Túlio Ornelas,在我使用 Kafka 构建一些通信时非常耐心地帮助我。
  • Gabriel Gomes,对这篇文章进行了如此细致的审阅,并帮助我提高了可读性(还纠正了我的英语错误哈哈哈)。
文章来源:https://dev.to/hcapucho/apache-kafka-101-introduction-567a
PREV
Java 音乐组合!音乐时间
NEXT
Web 开发人员必备的 10 大 VSCode 扩展