在上一期中,我们讨论了使用消息队列的好处。然后,我们回顾了消息队列产品的历史。现在看来,当我们需要在项目中使用消息队列时,Kafka 是首选产品。但是,当我们考虑特定要求时,它并不总是最佳选择。

数据库支持的队列

让我们再次使用我们的星巴克示例。最重要的两个要求是:

  • 异步处理,因此收银员无需等待即可接受下一个订单。

  • 坚持不懈,以便在出现问题时不会错过客户的订单。

消息订购在这里并不重要,因为咖啡机经常制作成批的相同饮料。可扩展性也不那么重要,因为队列仅限于每个星巴克门店。

星巴克队列可以在数据库表中实现。下图显示了它是如何工作的:

当收银员接受订单时,将在数据库支持的队列中创建一个新订单。然后,收银员可以接受另一个订单,而咖啡机则分批接取新订单。订单完成后,咖啡机会在数据库中将其标记为完成。然后,顾客在柜台领取咖啡。

内务管理作业可以在每天结束时运行,以删除已完成的订单(即那些状态为“完成”的订单)。

对于星巴克的用例,一个简单的数据库队列就可以满足要求,而不需要 Kafka。具有 CRUD(创建-读取-更新-删除)操作的订单表工作正常。

Redis支持的队列

数据库支持的消息队列仍然需要开发工作来创建队列表并从中读取/写入。对于预算有限且已经使用 Redis 进行缓存的小型初创公司,Redis 还可以用作消息队列。

有 3 种方法可以将 Redis 用作消息队列:

1.Pub/Sub 发布/订阅

2.List 列表

3.Stream 流

下图显示了它们的工作原理。

Pub/Sub 很方便,但有一些交付限制。当生产者将数据发布到同一密钥时,消费者订阅密钥并接收数据。限制是数据最多传递一次。如果使用者关闭且未收到已发布的数据,则该数据将丢失。此外,数据不会保留在磁盘上。如果 Redis 出现故障,则所有 Pub/Sub 数据都将丢失。Pub/Sub 适用于可以接受某些数据丢失的指标监控。

Redis 中的 List 数据结构可以构造 FIFO(先进先出)队列。使用者使用 BLPOP 在阻塞模式下等待消息,因此应应用超时。等待同一列表的消费者形成一个消费者组,其中每条消息仅由一个消费者使用。作为 Redis 数据结构,List 可以持久化到磁盘上。

Stream 解决了上述两种方法的限制。使用者选择从何处读取消息 – “$”表示新消息,“id”表示特定消息 ID,“0-0”表示从头开始读取。

总之,数据库支持和 Redis 支持的消息队列易于维护。如果它们不能满足我们的需求,专用的消息队列产品会更好。接下来我们将比较两个流行的选项。

对于需要可靠、可扩展和可维护系统的大型公司,请在以下方面评估消息队列产品:

  • 功能性

  • 性能

  • 可扩展性

  • 生态系统

下图比较了两种典型的消息队列产品:RabbitMQ 和 Kafka。

它们是如何工作的

RabbitMQ 的工作方式类似于消息传递中间件 – 它将消息推送给消费者,然后在确认时删除它们。这避免了 RabbitMQ 认为有问题的消息堆积。

Kafka 最初是为大规模日志处理而构建的。它会将消息保留到过期,并允许使用者按照自己的节奏拉取消息。

语言和 API

RabbitMQ 是用 Erlang 编写的,这使得修改核心代码具有挑战性。但是,它提供了非常丰富的客户端 API 和库支持。

Kafka 使用 Scala 和 Java,但也具有适用于 Python、Ruby 和 Node.js 等流行语言的客户端库和 API。

性能和可扩展性

RabbitMQ 每秒处理数万条消息。即使在更好的硬件上,吞吐量也不会高得多。

Kafka 每秒可以处理数百万条消息,具有很高的可扩展性。

生态系统

默认情况下,许多现代大数据和流式处理应用程序都集成了 Kafka。这使得它非常适合这些用例。

Message Queue使用案例

现在我们已经介绍了不同消息队列的功能,让我们看一些如何选择正确产品的示例。

日志处理和分析

对于具有购物车、订单和付款等服务的电子商务网站,我们需要分析日志以调查客户订单。

下图显示了使用“ELK”堆栈的典型体系结构:

  • ElasticSearch – 为全文搜索的日志编制索引

  • LogStash – 日志收集代理

  • Kibana – 用于搜索和可视化日志的 UI

  • Kafka – 分布式消息队列