本内容是对知名性能评测博主 Anton Putra Kafka vs RabbitMQ Performance 内容的翻译与整理, 有适当删减, 相关数据和结论以原作结论为准。
简介
在本视频中,我们将首先比较 Apache Kafka 和传统的 RabbitMQ 。然后,在第二轮测试中,会将 Kafka 与 RabbitMQ Streams 进行对比,后者在架构和使用场景上更接近 Kafka(RabbitMQ Streams 是一个相对较新的项目,旨在直接与 Kafka 竞争)。
与往常一样,我们将关注 四大核心指标:
- 吞吐量(Throughput)
---
以 每秒消息数(Messages per second) 衡量。 - 延迟(Latency)
---
追踪每条消息的发送和接收所需时间。 - 系统负载(Saturation)
---
包括 CPU 使用率 (相对于虚拟机的 CPU 限制)、内存使用情况 ,以及 磁盘操作(因为 Kafka 采用追加式日志,需要将每条消息存储到磁盘)。 - 客户端 CPU 负载
---
统计所有发送和接收消息的客户端的平均 CPU 使用率。
为了运行这些测试,我使用了 AWS 。消息代理部署在 i3en.large 规格的实例上,而客户端则运行在 EKS 集群 的 Graviton 实例 上。老实说,这次测试成本不低---
要让一个Kafka 代理崩溃,需要消耗大量计算资源。
测试设计
首先,我会快速讲解 Kafka 和 RabbitMQ。
在 Kafka 中,最常用的消息协议之一是 RPC 消息 ,它采用 二进制格式 ,相比 JSON 消息 体积更小。这不仅降低了消息代理的负载,还提高了 延迟 和 吞吐量 指标。此外,你可以在 gRPC 和 服务间通信(Service-to-Service Communication) 中复用这些消息。
在本次测试中,我使用 Device RPC 消息,它包含以下字段:
- UUID(设备唯一标识符)
- MAC 地址
- 固件版本
- 设备创建的时间戳
你可以在我的 GitHub 公开仓库 中找到源代码。
测试流程
- 在生产者端 ,我们使用 随机设备数据 生成 Device RPC 消息,并记录当前时间戳。
- 然后,我们 同时 将该消息发送到 Kafka 的Topic 和 RabbitMQ 队列(Queue)。
- 在消费者端 ,收到消息后,我们从
created_at
字段中提取时间戳,并计算 消息延迟。
注意 :我们不依赖 Kafka 或 RabbitMQ 内部指标 来测量延迟,而是直接在 客户端 端测量,这样测试方式对两者是 公平且准确 的。
如果你认为 测试设计 或 客户端源码 可以优化,欢迎提出建议或提交 Pull Request!
第一轮测试:Kafka vs. 传统 RabbitMQ
让我们开始第一轮测试,比较 Kafka 和 传统 RabbitMQ (后者主要将消息存储在 内存 中)。
刚开始,你就会注意到:
-
RabbitMQ 的消息发送和接收延迟比 Kafka 低近一半 。这对于某些应用场景可能至关重要,也可能无关紧要,但总体来说,RabbitMQ 的延迟更低。
-
右侧图表 显示了每个消息系统每秒 处理的消息数。
-
Kafka 的 CPU 使用率更高 ,因为它必须将 每一条消息写入磁盘。
-
左侧图表 显示 Kafka 正在 频繁进行磁盘写入 ,而 RabbitMQ 几乎不访问磁盘(甚至完全不触碰磁盘)。
另一个重要点 :Kafka 的 生产者 和 消费者 的 CPU 使用率 约为 RabbitMQ 客户端的两倍。
当 Kafka 的 CPU 使用率达到 50% 时,延迟开始显著上升 。也就是说,当 Kafka 的 CPU 超过 50% 时,其延迟会开始恶化,如果你对低延迟有严格要求,这一点需要特别注意。
RabbitMQ 的极限
- 当 RabbitMQ 处理达到 15,000 条消息/秒 时,CPU使用率达到 100% ,开始 崩溃,延迟急剧上升。
- 当 RabbitMQ 处理达到 33,000 条消息/秒 时,生产者和消费者 超时(默认超时 5 秒) ,开始 请求失败 。这意味着 RabbitMQ 的最大吞吐量约为 33,000 条消息/秒。
Kafka 的极限
-
Kafka 的 CPU 在更早的阶段就达到了 100% ,但它 仍然能够继续处理 所有消息。尽管 延迟增加 ,但 Kafka 仍 持续运作。
-
继续推高负载,我们发现 Kafka 在 230,000 条消息/秒 时达到极限。
接下来,我们打开每个图表,分析整个测试过程的数据。
数据分析
第一轮测试(Kafka vs. RabbitMQ):
- 吞吐量:Kafka 远超 RabbitMQ。
- 延迟 :RabbitMQ 低得多,这也是 选择 RabbitMQ 的主要原因。
- 磁盘操作 :(本次测试)Kafka 依赖 本地 SSD,提高了性能。
- CPU 使用率 :虽然Kafka使用了更多的CPU,但 即使达到 100% CPU 仍能持续运行 ,而不会像 RabbitMQ 那样CPU到达100%很快失败(因为RabbitMQ主要将数据存储在内存中?)。
- 客户端的CPU使用情况:
- 内存使用 :RabbitMQ CPU 100% 时,内存使用发生尖峰。
第二轮测试:Kafka vs. RabbitMQ Streams
在第二轮测试中,我们对比 Kafka 和 RabbitMQ Streams。
- 一开始,RabbitMQ Streams 的延迟就明显更高。
- 我使用了 官方 Golang 库 ,它采用 RabbitMQ Streams 专用的二进制协议。
- 这次,RabbitMQ 从一开始就开始写入磁盘 ,但其 CPU 使用率在测试初期远低于 Kafka。
RabbitMQ Streams 的极限
-
Kafka 在 12,000 条消息/秒 时 CPU 达到 100% ,延迟开始上升。
-
RabbitMQ 的 CPU 此时只有 15% ,我推测这是因为 RabbitMQ 处理每条消息的延迟较高。
-
当 RabbitMQ 处理达到 100,000 条消息/秒 时,CPU 100% ,并且性能进一步下降。
- 当 RabbitMQ 处理达到 135,000 条消息/秒 时,彻底失败。
Kafka 的极限
- 我继续增加 Kafka 的负载,最终 Kafka 在 272,000 条消息/秒 时崩溃。
接下来,我们打开所有图表,逐项分析数据。
数据分析
第二轮测试(Kafka vs. RabbitMQ Streams):
- RabbitMQ Streams 的吞吐量(和第一次测试所用的RabbitMQ相比)有所提升 ,但 整体速度比 Kafka 慢。
- RabbitMQ Streams 的延迟极高 ,只适用于 批量数据处理或非延迟敏感的场景 ,不适用于 低延迟应用。
- 每秒磁盘写入操作的次数:
- CPU使用情况:
- 客户端的平均CPU使用情况:
- 内存使用情况:
结论
- 如果你需要低延迟,并且 RabbitMQ 满足你的需求,那就选 RabbitMQ。
- 如果你需要高吞吐量、稳定性和可扩展性,Kafka 是更好的选择。
- 在第二轮测试中,Kafka 明显胜出。
如果你有更好的 RabbitMQ Streams 优化方案 ,欢迎分享,我愿意做 更新测试!