paint-brush
Kafka 与 RabbitMQ:找到最适合你的项目的方法经过@berdysheva
1,752 讀數
1,752 讀數

Kafka 与 RabbitMQ:找到最适合你的项目的方法

经过 Mariia Berdysheva8m2024/06/19
Read on Terminal Reader
Read this story w/o Javascript

太長; 讀書

Kafka 和 RabbitMQ 都是高吞吐量、低延迟场景的绝佳工具。选择取决于用例、架构和未来需求的具体情况。例如,Kafka 是长期交易事件存储的理想选择,而 RabbitMQ 则在需要协议兼容性和路由灵活性的场景中表现出色。当 RabbitMQ 和 Kafka 都适合时,请考虑您的未来需求。

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Kafka 与 RabbitMQ:找到最适合你的项目的方法
Mariia Berdysheva HackerNoon profile picture
0-item


在分布式系统和微服务中,消息代理必不可少。它们支持异步通信、分离服务并增强可靠性和可扩展性。现代架构严重依赖消息代理,使其成为许多设计模式中的关键组件。


Kafka 和 RabbitMQ 是两种最受欢迎的消息代理。它们以可靠、高效和适应性强而闻名,并拥有出色的文档、支持和社区。


RabbitMQ 是一种免费的开源解决方案,根据 Apache License 2.0 和 Mozilla Public License 2 获得双重许可。它允许您根据需要使用和修改它。它充当纯消息代理,支持多种协议并提供附加功能。


Kafka 也是根据 Apache 2.0 许可证开源的,它不仅仅是一个消息代理,而是一个分布式事件流平台。它提供了包括 Kafka Streams 在内的高级功能。


在比较 RabbitMQ 和 Kafka 时,没有“更好”的解决方案;而是要找到最适合您的架构和目标的解决方案。


本文将带您了解主要功能和特性,并直接比较两者。它旨在全面了解 Kafka 和 RabbitMQ 之间的差异,帮助您根据具体问题和要求做出明智的选择。


协议支持

RabbitMQ 支持各种协议,例如:

  1. MQTT(MQ 遥测传输)是一种轻量级协议,适用于带宽有限、延迟较高的网络,例如物联网 (IoT) 中的网络。它最初是为监控石油管道而创建的,现在被广泛用作发布-订阅消息传递协议。
  2. STOMP(简单文本导向消息传递协议)是一种简单、轻量级的基于文本的消息传递集成协议,非常适合通过 WebSocket 和 Web 使用。
  3. AMQP(高级消息队列协议)是 RabbitMQ 的主要协议,详细说明了各种路由选项。虽然 RabbitMQ 可以通过插件支持其他协议,但 AMQP 是其核心协议。


另一方面,Kafka 使用针对高吞吐量进行了优化的二进制 TCP 协议,并依赖于“消息集”抽象。此抽象允许网络请求将消息分组在一起,通过发送批量消息而不是单个消息来减少网络往返的开销。Kafka 的自定义协议为高负载场景的开发和优化提供了灵活性。


但是,自定义协议也有缺点。它将 Kafka 与其他消息代理隔离开来,导致缺乏互操作性。与与任何 AMQP 客户端兼容的 RabbitMQ 不同,Kafka 需要使用 Kafka 客户端。尽管如此,由于 Kafka 的受欢迎程度和社区的努力,Kafka 客户端可用于多种编程语言。

路由

RabbitMQ 和 Kafka 中的路由方法有很大不同。

RabbitMQ 路由

RabbitMQ路由的主要组件:

  • 生产者。生成并向 RabbitMQ 发送消息的应用程序。
  • Exchange。从生产者接收消息并将其路由到一个或多个队列。
  • 队列。存储消息。
  • 消费者。订阅队列并从队列接收消息的应用程序。RabbitMQ将消息推送给消费者,每个消费者仅从一个队列获取消息。

RabbitMQ
在深入研究交易所之前,我们应该澄清另外两个概念:

  1. 绑定。规则描述了如何将消息从 Exchange 路由到队列。通常,消费者在创建队列时会将其绑定到特定的 Exchange。
  2. Routing Key。在 RabbitMQ 中,Producer 无法直接指定一条消息所属的 Queue,Exchange 根据 Producer 提供的 Routing Key 来路由消息,Routing Key 是由一个或多个用点分隔的字符串组成。


Exchange 有四种类型:

  1. 默认。使用路由键中的队列名称将消息直接路由到队列。
  2. 扇出。将消息广播到所有绑定的队列,忽略路由键。
  3. 直接。根据路由键和队列提供的绑定键之间的精确匹配将消息路由到队列。
  4. 主题。允许基于路由键的模式匹配的复杂路由规则,支持通配符:
  • *(星号) 匹配一个单词。

  • #(hash) 匹配零个或多个单词。


例如,使用路由键“apple.*.banana”绑定的队列将接收带有“apple.orange.banana”“apple.strawberry.banana”等键的消息。使用#.banana绑定的队列将接收带有“apple.banana”“apple.orange.banana”等键的消息。


卡夫卡

Kafka 的路由比较简单,主要组件有:

  • 生产者。与 RabbitMQ 类似,它将消息发送到主题 (Topic)。
  • 主题。存储消息。生产者指定要发送消息的主题。
  • 分区。每个主题分为多个分区,代表消息的物理存储。生产者可以指定一个密钥来路由消息,确保所有具有相同密钥的消息都属于同一个分区。
  • 消费者。与 RabbitMQ 消费者不同, Kafka 消费者从主题中提取消息。它们一次只能从一个主题读取消息。

卡夫卡

与 RabbitMQ 相比,Kafka 的路由功能有限。它不是为精细路由而设计的,而是为高性能和可扩展性而设计的。


这里需要注意一件重要的事情:


RabbitMQ 中,当消费者从队列收到消息时,他们会“窃取”该消息。如果成功确认,其他消费者将不会收到该消息。如果 Kafka 消费者属于同一个消费者组,则其行为方式相同。消费者组是 Kafka 的一个抽象概念,允许多个消费者独立读取同一个主题,确保每个消费者组处理所有主题消息。

持久性和耐久性

在 RabbitMQ 中,耐用性和持久性是截然不同的特征:


  • 持久性。这是队列和交换器的一个属性。队列有两种类型:持久队列和临时队列。持久队列(或交换器)将其元数据存储在磁盘上,并且可以在代理重新启动后继续存在。临时队列则不然。

  • 持久性。持久队列不保证消息持久性。要使其持久,您必须配置持久性。发布者发送消息时,可以指定持久性属性。在这种情况下,消息将存储在内部磁盘存储中,并在代理重新启动后可用。


Kafka 将所有内容存储在磁盘上。与 RabbitMQ 在消费者确认后删除消息不同,Kafka 会保留所有消息,直到它们达到生存时间 (TTL) 或磁盘大小限制。它允许不同或相同的消费者组重新处理消息。

可扩展性

RabbitMQ 和 Kafka 都支持集群,其中多个代理协同工作。


在 RabbitMQ 中,集群可提高可用性并确保数据安全。如果我们谈论性能,那么垂直扩展是提升 RabbitMQ 的首选方法。水平扩展可能会增加大量同步开销。通常,您更愿意拥有一个 3 个代理的集群,以确保在一个代理发生故障时可用性。


RabbitMQ 不支持开箱即用的队列分区,但值得一提的是,它具有一致性哈希交换插件,这可以帮助您扩展集群甚至分配负载。


Kafka 可高效扩展。它不仅提供可用性和数据安全性,而且还提高了数据处理的吞吐量。这里的关键概念是分区。每个主题都有可配置的分区数量。每个分区都独立于其他分区运行,充当物理数据存储和处理。您可以在集群中复制每个分区,从而确保容错能力。生产者和消费者仅使用主(或主要)分区。如果具有此分区的代理发生故障,系统将从副本中选择一个新的主分区。


选择正确的分区数量至关重要。如果节点发生故障,大量的分区会减慢系统恢复速度。相反,它会限制消费者组的吞吐量和并行度。在一个消费者组中,每个分区只能与一个消费者一起工作(这实际上是应用程序中的一个线程)。因此,拥有三个分区是没有意义的,因为其余的消费者将处于空闲状态。


Kafka 主题


订购

RabbitMQ 保证单个队列内的顺序。一个消费者将按顺序处理消息。但是,如果有多个消费者,情况就会发生变化。如果一个消费者失败,系统会将未确认的消息返回到队列,但下一个消费者可能已经在处理下一批消息。那么,有什么选择呢?


  1. 使用 Kafka!Kafka 保证一个分区内的排序(这是直观的,因为它一次只能处理一个分区)。但是,Kafka 不保证整个主题的排序。通常,在客户 ID 或付款 ID 内保持排序是必不可少的。因此,如果生产者使用正确的分区键,您可以为系统实现准确的排序。
  2. 使用一致性哈希交换插件。通过单活动消费者选项,它将 RabbitMQ 转换为 Kafka。它为您提供“分区”,并确保每个分区只有一个消费者可以工作。

送货保证

RabbitMQ 和 Kafka 提供“至少一次”传递保证,这意味着可能会出现重复,但消息至少会被完全处理一次。


Kafka 有更多交付特性:

  • 幂等生产者。在 Kafka 中,您可以配置生产者来替换重复的消息。RabbitMQ 生产者可以将重复的消息发送到队列。
  • Kafka 处理中的精确一次交付。精确一次 - 是最强的保证。它确保每条消息只处理一次,不多也不少。在 Kafka 中,您可以通过 Kafka 事务获得它:当您从一个 Kafka 主题消费并写入另一个 Kafka 主题时。

其他功能

正如前面提到的,Kafka 通过放弃路由灵活性,带来了强大的功能。


Kafka 提供了强大的流处理库:

  • Kafka Streams。允许在 Kafka 内进行实时数据处理和转换。
  • KSQL。提供类似 SQL 的接口来查询和转换流数据,创建由 Kafka 主题支持的持久表抽象。


使用 Kafka Streams,您可以对主题执行时间聚合并将结果推送到另一个主题或数据库。


假设您有一个包含不同货币对汇率的主题,并且您想要汇总时间段内(5 分钟、30 分钟、1 小时等)的开盘-最高-最低-收盘图(也称为 OHLC)数据。


一种选择是将数据存储在时间序列数据库中,这适合进行此类处理。但是,如果您有 Kafka,则不需要这样做。使用简单的 Kafka Stream 聚合,您可以在 Kafka 主题之上计算 OHLC 数据,并将结果放入任何数据库中以供进一步查询。


Kafka 还允许您将处理后的消息表示为表。它将聚合结果放入表抽象中,您可以通过 KSQL 访问该表。这样的表状态是持久的。如果代理重新启动,它将从相应主题恢复最新状态。


如我们所见,Kafka 超越了基本的消息代理功能,进入了实时处理和 ETL 领域。

结论

Kafka 和 RabbitMQ 都是高吞吐量、低延迟场景的绝佳工具。选择取决于用例、架构和未来需求的具体情况。例如,Kafka 是长期交易事件存储的理想选择,而 RabbitMQ 则在需要协议兼容性和路由灵活性的场景中表现出色。当 RabbitMQ 和 Kafka 都适合时,请考虑您的未来需求。