ITPUB

消息队列性能比拼: Kafka vs RabbitMQ

来源:旅途散记

本内容是对知名性能评测博主 Anton Putra Kafka vs RabbitMQ Performance[1] 内容的翻译与整理, 有适当删减, 相关数据和结论以原作结论为准。

简介

我们将首先比较 Apache Kafka 和传统的 RabbitMQ。然后,在第二轮测试中,会将 Kafka 与 RabbitMQ Streams 进行对比,后者在架构和使用场景上更接近 Kafka(RabbitMQ Streams 是一个相对较新的项目,旨在直接与 Kafka 竞争)。

与往常一样,我们将关注 四大核心指标:

  1. 吞吐量(Throughput)--- 以 每秒消息数(Messages per second) 衡量。
  2. 延迟(Latency)--- 追踪每条消息的发送和接收所需时间。
  3. 系统负载(Saturation)--- 包括 CPU 使用率(相对于虚拟机的 CPU 限制)、内存使用情况,以及 磁盘操作(因为 Kafka 采用追加式日志,需要将每条消息存储到磁盘)。
  4. 客户端 CPU 负载--- 统计所有发送和接收消息的客户端的平均 CPU 使用率。

为了运行这些测试,我使用了 AWS。消息代理部署在 i3en.large 规格的实例上,而客户端则运行在 EKS 集群 的 Graviton 实例 上。老实说,这次测试成本不低---要让一个Kafka 代理崩溃,需要消耗大量计算资源。


测试设计

首先,我会快速讲解 Kafka 和 RabbitMQ。

在 Kafka 中,最常用的消息协议之一是 RPC 消息,它采用 二进制格式,相比 JSON 消息 体积更小。这不仅降低了消息代理的负载,还提高了 延迟 和 吞吐量指标。此外,你可以在 gRPC 和 服务间通信(Service-to-Service Communication) 中复用这些消息。

Image

在本次测试中,我使用 Device RPC 消息,它包含以下字段:

  • UUID(设备唯一标识符)
  • MAC 地址
  • 固件版本
  • 设备创建的时间戳
Image

你可以在我的 GitHub 公开仓库[2] 中找到源代码。

Image

测试流程

  1. 在生产者端,我们使用 随机设备数据 生成 Device RPC 消息,并记录当前时间戳。
  2. 然后,我们 同时 将该消息发送到 Kafka 的Topic 和 RabbitMQ 队列(Queue)。
  3. 在消费者端,收到消息后,我们从 created_at 字段中提取时间戳,并计算 消息延迟。

注意:我们不依赖 Kafka 或 RabbitMQ 内部指标 来测量延迟,而是直接在 客户端 端测量,这样测试方式对两者是 公平且准确 的。

Image

如果你认为 测试设计 或 客户端源码 可以优化,欢迎提出建议或提交 Pull Request!


第一轮测试:Kafka vs. 传统 RabbitMQ

让我们开始第一轮测试,比较 Kafka 和 传统 RabbitMQ(后者主要将消息存储在 内存 中)。

刚开始,你就会注意到:

Image
  • RabbitMQ 的消息发送和接收延迟比 Kafka 低近一半。这对于某些应用场景可能至关重要,也可能无关紧要,但总体来说,RabbitMQ 的延迟更低。

  • 右侧图表 显示了每个消息系统每秒 处理的消息数。

  • Kafka 的 CPU 使用率更高,因为它必须将 每一条消息写入磁盘。

  • 左侧图表 显示 Kafka 正在 频繁进行磁盘写入,而 RabbitMQ 几乎不访问磁盘(甚至完全不触碰磁盘)。

另一个重要点:Kafka 的 生产者 和 消费者 的 CPU 使用率 约为 RabbitMQ 客户端的两倍。

Image

当 Kafka 的 CPU 使用率达到 50% 时,延迟开始显著上升。也就是说,当 Kafka 的 CPU 超过 50% 时,其延迟会开始恶化,如果你对低延迟有严格要求,这一点需要特别注意。

RabbitMQ 的极限

Image
  • 当 RabbitMQ 处理达到 15,000 条消息/秒 时,CPU使用率达到 100% ,开始 崩溃,延迟急剧上升。
  • 当 RabbitMQ 处理达到 33,000 条消息/秒 时,生产者和消费者 超时(默认超时 5 秒),开始 请求失败。这意味着 RabbitMQ 的最大吞吐量约为 33,000 条消息/秒。

Kafka 的极限

Image
  • **Kafka 的 CPU 在更早的阶段就达到了 100%**,但它 仍然能够继续处理 所有消息。尽管 延迟增加,但 Kafka 仍 持续运作。

  • 继续推高负载,我们发现 Kafka 在 230,000 条消息/秒 时达到极限。

接下来,我们打开每个图表,分析整个测试过程的数据。

数据分析

第一轮测试(Kafka vs. RabbitMQ):

  • 吞吐量:Kafka 远超 RabbitMQ。
Image
  • 延迟:RabbitMQ 低得多,这也是 选择 RabbitMQ 的主要原因。
Image
  • 磁盘操作:(本次测试)Kafka 依赖 本地 SSD,提高了性能。
Image
  • CPU 使用率:虽然Kafka使用了更多的CPU,但 即使达到 100% CPU 仍能持续运行,而不会像 RabbitMQ 那样CPU到达100%很快失败(因为RabbitMQ主要将数据存储在内存中?)。
Image
  • 客户端的CPU使用情况:
Image
  • 内存使用:RabbitMQ CPU 100% 时,内存使用发生尖峰。
Image

第二轮测试:Kafka vs. RabbitMQ Streams

在第二轮测试中,我们对比 Kafka 和 RabbitMQ Streams。

  • 一开始,RabbitMQ Streams 的延迟就明显更高。
  • 我使用了 官方 Golang 库,它采用 RabbitMQ Streams 专用的二进制协议。
  • 这次,RabbitMQ 从一开始就开始写入磁盘,但其 CPU 使用率在测试初期远低于 Kafka。
Image

RabbitMQ Streams 的极限

  • Kafka 在 12,000 条消息/秒 时 CPU 达到 100% ,延迟开始上升。

  • RabbitMQ 的 CPU 此时只有 15% ,我推测这是因为 RabbitMQ 处理每条消息的延迟较高。

  • 当 RabbitMQ 处理达到 100,000 条消息/秒 时,CPU 100% ,并且性能进一步下降。

Image
  • 当 RabbitMQ 处理达到 135,000 条消息/秒 时,彻底失败。

Kafka 的极限

  • 我继续增加 Kafka 的负载,最终 Kafka 在 272,000 条消息/秒 时崩溃。
Image

接下来,我们打开所有图表,逐项分析数据。


数据分析

第二轮测试(Kafka vs. RabbitMQ Streams):

  • RabbitMQ Streams 的吞吐量(和第一次测试所用的RabbitMQ相比)有所提升,但 整体速度比 Kafka 慢。
Image
  • RabbitMQ Streams 的延迟极高,只适用于 批量数据处理或非延迟敏感的场景,不适用于 低延迟应用。
Image
  • 每秒磁盘写入操作的次数:
Image
  • CPU使用情况:
Image
  • 客户端的平均CPU使用情况:
Image
  • 内存使用情况:
Image

结论
  • 如果你需要低延迟,并且 RabbitMQ 满足你的需求,那就选 RabbitMQ。
  • 如果你需要高吞吐量、稳定性和可扩展性,Kafka 是更好的选择。
  • 在第二轮测试中,Kafka 明显胜出。

如果你有更好的 RabbitMQ Streams 优化方案,欢迎分享,我愿意做 更新测试!

参考资料
[1] 

Kafka vs RabbitMQ Performance: https://www.youtube.com/watch?v=UPkOsXKG4ns

[2] 

GitHub 公开仓库: https://github.com/antonputra/tutorials/tree/main/lessons/218

直播预告
7月10日,ITPUB携手行业专家围绕“ AI破局:开源、增效与个体崛起”这一主题开展线上直播分享,点击下方卡片预约直播:
7月11日,ITPUB携手行业专家围绕“ Agent设计路线图”这一主题开展线上直播分享,点击下方卡片预约直播:

Image