消息代理与数据库和监视

时间:2018-01-04 16:04:59

标签: database rabbitmq message-queue

我的问题与这个问题有一些相似之处: Why do we need message brokers like RabbitMQ over a database like PostgreSQL?

在我目前的(半专业)项目中,我还决定是去数据库,基于消息代理(例如使用RabbitMQ)还是完全不同的解决方案。

让我们想象2个工具,工具A和工具B. 每当工具A运行并完成时,可能可以为工具B执行操作。工具A的执行需要一段时间(> 60秒),并且通常对工具B没有任何操作。工具A为工具B提供了一些元数据,因此工具B知道该怎么做。

基于消息的解决方案:建立工具B正在使用的消息队列。如果工具A已执行工具B应运行,工具A会将消息(包括元数据)发布到工具B接收的队列中,以便工具B将使用消息中的元数据运行。

数据库解决方案:每当工具A运行时,它都会添加一个数据库记录,例如:时间戳,元数据和状态" RUNNING"。如果工具A已执行工具B应运行,则会将DB记录状态更新为" NEXT_TOOL_B"。工具B不断向DB查询" NEXT_TOOL_B"状态。如果找到某些内容,工具B将使用DB记录中的元数据运行。

虽然我知道数据库解决方案的缺点,例如工具B的常量轮询,我在基于消息的解决方案中遗漏了它的一个特性:

每当第三个工具,比如工具C,例如一个控制面板用户界面,想知道当前状态,它也可以随时查询数据库,它会找到一个" RUNNING"状态如果工具A仍在工作。在消息解决方案中,我并没有真正看到一种方法来监控"状态,除非完成消息将在队列中。

所以我的问题是,您是否可以考虑使用消息或任何其他没有轮询的方法实现此目的?

3 个答案:

答案 0 :(得分:6)

问题中描述的场景是系统的场景,它由多个不同的部分组成,它们协同工作以实现功能。在这种情况下,您有三个不同的进程{A,B,C},以及数据库和可选的消息队列。作为其存在目的的一部分,所有系统接受一个或多个输入,执行一些过程,并产生一个或多个输出。在您的情况下,您需要的输出之一是系统的状态及其处理,这不是一个完全不合理的事情。

队列或数据库?

现在,直到你的问题。为什么使用消息队列而不是数据库?两者都是系统的类似组件,因为它们执行一些存储容量。您可能会在冰箱制造工厂中提出同样的问题 - 何时在装配线上使用货架而不是仓库更有意义?

数据库就像仓库一样 - 它们旨在容纳许多不同的东西并使它们保持相对直接。一个好的仓库允许用户快速查找仓库中的东西,并避免丢失零件和材料。如果它进入,它可以很容易地退出,但不是立即。

另一方面,消息队列就像位于装配线中操作员站附近的货架。零件从之前的操作累积到那里等待由运行该站的人消耗。这些架子设计用于容纳少量相同的东西 - 就像软件系统中的消息队列一样。它们靠近工人,所以当下一部分准备好工作时,它可以很快被检索(而不是去仓库,可能需要几分钟或更长时间)。此外,工人可以立即看到货架上的物品 - 如果货架是空的,工人可能会休息并等待它再次累积一部分或两部分。

最后,如果工厂的一部分严重过度生产(当发生这种情况时我们不喜欢它,因为它表明浪费),那么货架将会不堪重负,而且需要超额被放入仓库。信不信由你,这种情况一直发生在工厂 - 有时候车站会短暂停机,仓库可以作为长期缓冲。

何时使用其中一种?

所以 - 回到问题。如果您希望消息的生成通常与消息的消耗相匹配,则需要使用消息队列,并且需要检索速度。你不希望事情长时间留在队列中。软件队列系统,例如RabbitMq,也执行一些非常特定的功能 - 比如确保一个处理器只处理一个作业,并且如果第一个处理器发生故障,它可以被另一个处理器拾取。

另一方面,您将使用数据库来处理需要跨多个处理步骤持久化状态的事物。您的工作状态是应该存储在数据库中的完美示例。继续工厂类比 - 将其视为在每个步骤完成后发送回生产计划员的报告。生产计划员将把它保存在数据库中。

您可能还希望在队列可能已满的情况下使用数据库,或者在一个作业步骤与另一个作​​业步骤之间数据不丢失的情况下使用数据库。例如,制造工厂通常将其成品存储在仓库中,等待运送给客户。在您的应用程序中使用数据库满足所有长期(超过几秒)的存储需求。

底线

大多数可扩展的软件系统都需要队列和数据库,关键是知道何时使用每个队列和数据库。

希望这有一定程度的意义。

答案 1 :(得分:0)

您可以使队列的生产者和消费者更新NoSQL数据库或RDBMS中的表。这将使您可以在任何给定时间查看请求的状态。它还将使您无需进行轮询即可利用推送消息的优势。

答案 2 :(得分:0)

免责声明:我是cluster-tasks-service-CTS的作者,是提出的解决方案或其他使用其他相关工具时要考虑的模式。

问题是,从一般体系结构的角度来看,您描述的功能似乎需要两种解决方案:

  • 工具B作为工具A完成工作的结果而执行的部分是事件驱动流中的经典之作。邮件通常对此更有效,但请继续阅读...
  • 您想要对状态进行一些状态观察/监视的部分肯定提出了持久化状态的要求(嗯,是的,甚至在内存中也没有,至少在分布式内存中也是如此) ,因为稍后您需要一个群集等)

我想说基于数据库的队列将是一个解决方案。与非基于DB的方法相比,基于DB的队列肯定遭受较低的吞吐量。但是,它为您带来一些好处,例如:

  • 确保持久性,除非发生真正的灾难,否则任务/消息不会丢失,然后队列是问题中最少的
  • 通过数据库同步智能任务管理,无需复杂的系统拓扑,主/从问题,故障转移等
  • 获得诸如嵌入式解决方案这样的队列要容易得多-与单独的Redis / Rabbit / Kafka安装/服务相比,运营成本非常低

对于CTS-这是一个基于DB的群集感知任务分配和管理系统(由使用中的应用程序提供并运行嵌入式程序),通过将工具B作为工具排队的任务运行,可以解决您的问题A在其处理结束时包含所有相关数据。 同时,工具C可以使用CTS的API来检查任务的状态并根据需要可视化它们。