database - 消息代理与数据库和监控

标签 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 不断在数据库中查询状态为“NEXT_TOOL_B”的记录。如果它发现了什么,工具 B 将使用数据库记录中的元数据运行。

虽然我知道数据库解决方案的缺点,例如来自工具 B 的持续轮询,我在基于消息的解决方案中错过了它的一个功能:

每当第三个工具时,说工具 C,例如一个控制面板 UI,想知道当前状态它也可以随时查询数据库,如果工具 A 仍在工作,它会发现“RUNNING”状态。在消息解决方案中,除非完成消息将在队列中,否则我真的看不到“监视”状态的方法。

所以我的问题是,您能否想出使用消息或任何其他无需轮询的方法来实现此目的的方法?

最佳答案

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

队列还是数据库?

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

数据库就像仓库 - 它们旨在容纳许多不同的东西,并使它们保持相对整齐。一个好的仓库可以让用户快速的找到仓库里的东西,避免丢失零件和 Material 。如果它进去,它可以很容易地回来,但不是立即。

另一方面,消息队列就像装配线中位于运算符(operator)站附近的货架。先前操作的零件堆积在那里,等待操作站的人员消耗。货架旨在容纳少量相同的东西——就像软件系统中的消息队列一样。它们离 worker 很近,所以当下一个零件准备好工作时,可以很快取回(而不是去仓库,这可能需要几分钟或更长时间)。此外,工作人员可以立即看到货架上的元素 - 如果货架是空的,工作人员可能会休息一下,等待货架再次堆积一两件。

最后,如果工厂的某个部分严重超产(我们不喜欢这种情况发生,因为它表明浪费),那么货架就会被压垮,超额部分将需要放入仓库。信不信由你,这种情况在工厂中经常发生 - 有时站点会短暂停机,而仓库充当长期缓冲。

何时使用其中之一?

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

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

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

底线

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

希望这在某种程度上是有意义的。

关于database - 消息代理与数据库和监控,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48099098/

相关文章:

node.js - 防止 NodeJS 中的 MongoDB 多重连接

Redis 发布/订阅 vs Rabbit MQ

c# - 跨集群的 MassTransit 请求和响应

c - 使用 Windows 解决 GTK+/Queue 中的内存泄漏问题

php - Laravel - 从一个表中获取另一个表中不存在的记录并附加 where 子句

linux - 使用变量作为非sudo用户+创建数据库

.net - RabbitMQ 与 .NET

c - 两个 fork 进程之间的消息队列导致来自 msgsnd 的参数无效

queue - 替换 jms 队列中的消息

Python + MongoDB 文档版本控制