在上一期文章中,我们讨论了使用消息队列的好处。然后我们回顾了消息队列产品的历史。如今,当我们需要在项目中使
用消息队列时,Kafka 似乎是首选产品。然而,当我们考虑具体需求时,它并不总是最佳选择。
让我们再次使用我们的星巴克示例。两个最重要的需求是:
- 异步处理,这样收银员可以接受下一个订单而无需等待
- 持久性,这样如果出现问题,客户的订单不会丢失
消息顺序在这里不太重要,因为咖啡师经常批量制作相同的饮料。可扩展性也不太重要,因为队列限制在每个星巴克位置。
星巴克队列可以在数据库表中实现。下图显示了它是如何工作的:

当收银员接受订单时,在数据库支持的队列中创建一个新订单。然后收银员可以接受另一个订单,而咖啡师批量取新订单。订单完成后,咖啡师在数据库中标记为完成。然后客户在柜台取咖啡。
每日结束时可以运行一个清理作业来删除完成的订单(即那些状态为”DONE”的订单)。
对于星巴克的用例,简单的数据库队列无需 Kafka 即可满足需求。具有 CRUD(创建 - 读取 - 更新 - 删除)操作的订单表工作正常。
数据库支持的消息队列仍然需要开发工作来创建队列表并从中读/写。对于预算有限且已经使用 Redis 进行缓存的小型初创公司,Redis 也可以用作消息队列。
有 3 种方式使用 Redis 作为消息队列:
- Pub/Sub
- List
- Stream
下图显示了它们如何工作:

Pub/Sub 很方便但有一些传递限制。消费者订阅一个键,当生产者将数据发布到同一个键时接收数据。限制是数据最多传递一次。如果消费者宕机且没有收到发布的数据,该数据就会丢失。此外,数据不会持久化到磁盘。如果 Redis 宕机,所有 Pub/Sub 数据都会丢失。Pub/Sub 适用于某些数据丢失可接受的指标监控。
Redis 中的 List 数据结构可以构建 FIFO(先进先出)队列。消费者使用 BLPOP 以阻塞模式等待消息,所以应该应用超时。等待同一个 List 的消费者形成一个消费者组,其中每条消息只被一个消费者消费。作为 Redis 数据结构,List 可以持久化到磁盘。
Stream 解决了上述两种方法的限制。消费者选择从哪里读取消息 - ”$“表示新消息,"
总之,数据库支持和 Redis 支持的消息队列易于维护。如果它们不能满足我们的需求,专用消息队列产品更好。接下来我们将比较两个流行选项。
对于需要可靠、可扩展和可维护系统的大型公司,根据以下方面评估消息队列产品:
- 功能
- 性能
- 可扩展性
- 生态系统
下图比较了两个典型的消息队列产品:RabbitMQ 和 Kafka。

RabbitMQ 像消息中间件一样工作 - 它将消息推送给消费者,然后在确认时删除它们。这避免了 RabbitMQ 认为有问题的消息堆积。
Kafka 最初是为大规模日志处理构建的。它保留消息直到过期,让消费者按照自己的节奏拉取消息。
RabbitMQ 用 Erlang 编写,这使得修改核心代码具有挑战性。然而,它提供非常丰富的客户端 API 和库支持。
Kafka 使用 Scala 和 Java,但也有用于 Python、Ruby 和 Node.js 等流行语言的客户端库和 API。
RabbitMQ 每秒处理数万条消息。即使在更好的硬件上,吞吐量也不会高太多。
Kafka 每秒可以处理数百万条消息,具有高可扩展性。
许多现代大数据和流应用默认集成 Kafka。这使得它成为这些用例的自然选择。
现在我们已经涵盖了不同消息队列的功能,让我们看看一些如何选择正确产品的示例。
对于具有购物车、订单和支付等服务的电商网站,我们需要分析日志来调查客户订单。
下图显示了一个使用”ELK”栈的典型架构:
- ElasticSearch - 索引日志进行全文搜索
- LogStash - 日志收集代理
- Kibana - 搜索和可视化日志的 UI
- Kafka - 分布式消息队列

本文为学习目的的个人翻译,译文仅供参考。
原文链接:How to Choose a Message Queue?。
版权归原作者或原刊登方所有。本文为非官方译本;如有不妥,请联系删除。