消息队列与任务队列的区别

38

我想知道它们之间的区别。它们描述的是同一件事吗?

Google App Engine 服务中的任务队列,是消息队列的实现吗?

5个回答

44
我曾在Facebook的一些开发者社区组上提出了类似的问题。这并不是针对GoogleAppEngine的特定问题,而是更为普遍地询问RabbitMQ和Celery之间的用例差异。以下是我收到的回复,它们与主题相关且相当清楚地阐明了消息队列和任务队列之间的区别。
我问道:
“是否可以说‘Celery是一个QueueWrapper/QueueFramework,它消除了管理内部queueManagement/queueAdministration等活动的复杂性’?”
“我理解书中所说的‘Celery是一个任务队列’和‘RabbitMQ是一个消息代理’。然而,作为第一次使用Celery的用户,这似乎有点令人困惑,因为我们一直认为RabbitMQ是‘队列’。”
“请帮忙解释一下Celery与RabbitMQ的区别和作用。”

我收到了来自Abu Ashraf Masnun的回复

任务队列和消息队列。RabbitMQ 是一种“消息队列”。它接收消息并传递消息。
Celery 是一个任务队列。它接收带有相关数据的任务,运行它们并传递结果。
让我们暂时忘记 Celery。让我们谈谈 RabbitMQ。通常我们会做什么?我们的 Django/Flask 应用程序将向队列发送消息。我们会有一些正在运行的 worker,它们将在特定队列中等待新的消息。当新消息到达时,它开始工作并处理任务。
Celery 精美地管理了整个过程。我们不再需要学习或担心 AMQP 或 RabbitMQ 的细节。我们可以使用 Redis 或甚至数据库 (例如 MySQL) 作为消息代理。Celery 允许我们使用我们的 worker 代码定义“任务”。当我们需要在后台 (甚至前台) 做某事时,我们只需调用此任务 (进行即时执行) 或将此任务安排为延迟处理。Celery 将处理消息传递和运行任务。它将启动知道如何运行您定义的任务并存储结果的 worker。因此,您稍后可以查询任务结果,甚至是任务进度。
您也可以将 Celery 用作 cron job 的替代方案 (尽管我不太喜欢它)!

另一个回复,我收到了Juan Francisco Calderon Zumba的回复。

我的理解是,Celery只是实现事件生产者/消费者的高度抽象。它省去了您需要执行的一些痛苦操作,例如与rabbitmq一起工作。Celery本身不是队列。事件队列存储在您选择的系统中,Celery帮助您在不必从头开始编写生产者/消费者的情况下处理此类事件。

最终,以下是我得出的最终学习成果:

Celery是一个队列封装/框架,它消除了直接操作RabbitMQ时涉及的底层AMQP机制/架构的复杂性。


答案仍然让我感到困惑。我们何时应该使用任务队列而不是消息队列? - papalagi
1
@papalagi,将消息队列视为概念的低级构建块。 并将任务队列视为消息队列的实现,以帮助实现任务编排 - 它是一个包装器/框架,可在消息队列上实现可运行任务的队列。 - Rakib

12

GAE的任务队列是一种允许应用程序进行后台处理的方式,它们不会像消息队列那样发挥相同的作用。它们是非常不同的东西,提供不同的功能。

消息队列是在进程、线程和系统之间共享信息的机制。

AppEngine任务队列是一种让AppEngine应用程序告诉自己,“我需要做这个,但我将在客户端请求的上下文之外稍后执行它”的方法。


3
在我所知道的情况下,App Engine上的消息队列和拉取队列之间没有功能上的区别。 - Nick Johnson

9
可能会因上下文而异,但以下是我的理解:

消息队列

消息队列是消息代理的一部分 - 一个队列的数据结构实现,您可以:

  1. 将消息入队/生成/推送/发送到。
  2. 从中取消排队/消耗/拉取/接收消息。
  3. 提供FIFO排序。

任务队列

另一方面,任务队列是用于处理任务的:

  1. 以所需的速度进行处理 - 您的系统可以同时处理多少个任务?可能取决于机器上的CPU核数,或者如果您在Kubernetes上,则取决于节点数及其大小。这涉及并发控制,或者不太酷的术语“缓冲”。
  2. 以异步方式进行处理 - 非阻塞任务处理。在后台处理任务,因此在启动任务后,您的主进程可以去做其他事情。通过HTTP的服务器API是一个流行的用例,其中您希望快速响应客户端,因为HTTP请求通常具有短暂的超时时间(≤ 30s),特别是当您的API由最终用户触发时(人类不耐烦)。如果您的任务需要花费更长的时间,请考虑将其移到后台,并给出API响应,例如“好的,我已收到您的请求,在拥有时间时我会处理它。”

它们的区别

正如您所看到的,消息队列和任务队列关注不同的方面,它们可能重叠,但不一定。

任务队列的一个示例但不是消息队列 - 如果您的任务不关心排序 - 每个任务不依赖于彼此 - 那么您不需要FIFO数据结构“队列”。您可以,但不必。您只需要一个地方来存储缓冲的任务,例如池、简单的SQL/NoSQL数据库甚至S3都足够了。

相反的例子是推送通知。您使用消息队列,但不一定使用任务队列。服务器生成事件/通知并希望将其传递给客户端。服务器将通知推入队列中。客户端在准备好这样做时从队列中消耗/拉取通知。可使用GCP PubSub、AWS SNS等产品进行此操作。

要点

由于并发控制,任务队列通常比消息队列更复杂,更不用说如果您想进行水平扩展,例如分布式工作器优化并发性。

像Celery这样的工具是任务队列+消息队列融为一体。我所知道的没有像Celery这样同时做两者的工具,猜测这就是它如此受欢迎的原因(在NodeJS中的替代工具是Bull或Bee,如果您知道更多,请告诉我!)。

最近,我的公司不得不实现任务队列。在查找适当的工具时,这两个术语让我非常困惑,因为我有点知道我想要什么,但不知道人们称之为什么以及我应该使用哪些关键字进行搜索。

我个人很少使用AppEngine,无法回答这个问题,但您可以始终检查上述要点,看它是否满足需求。


一个任务队列但不是消息队列的例子 - 如果你的任务不关心顺序。如果你的任务不关心顺序,并且你不会使用队列来管理它们,那么你并没有使用任务队列,而是使用了另一种数据结构。 - Alan Evangelista
@AlanEvangelista 是的,按照FIFO队列的定义(也许是学术定义),这是正确的。但实际上,像简单队列服务SQS这样的服务,并不一定根据您的配置有序。我认为“队列”这个词也被用作提供缓冲和可靠性的广义术语,以应对大量流量。 - Shawn

0
如果我们只谈论功能,那么很难区分它们之间的差异。在我的公司里,由于我们对这两者的误解,我们尝试并惨败了。我们创建了工作队列(也称任务队列、调度器或计划任务),并将其用于长轮询。我们将任务计划设置为 5 秒后触发轮询代码(延迟)。该代码发送请求并检查响应。如果条件不符合,我们会再次创建一个任务来扩展轮询,否则不会扩展。这是一个需要大量数据库、网络和计算资源的过程。我们的新用例要求快速响应,因此我们必须将延迟减少到 0.1 秒,这会导致每次轮询浪费大量资源。因此,这是一个技术实现相同目标但效率不同的主要例子。因此,答案在于消息队列和任务队列试图实现的目标不同。阅读推荐:https://dev59.com/r4_ea4cB1Zd3GeqPPYV5#32804602

-2

如果你从浏览器的JavaScript运行环境或Nodejs的JavaScript运行环境来考虑,答案是:

消息队列微任务队列(例如Promises)之间的区别在于,微任务队列比消息队列具有更高的优先级,这意味着微任务队列中的Promise任务将在消息队列中的回调函数之前执行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接