为什么数据库作为队列那么糟糕?[关闭]


33

我刚刚读了这篇文章,我很困惑。

假设有1个webapp和1个不同的应用程序充当“工作者”,它们共享同一个数据库

哦,我说“分享” ..但是这篇文章警告了什么?:

第四,在应用程序(或服务)之间共享数据库是一件坏事。在其中放置无定形共享状态太诱人了,在您不知道它的情况下,您将拥有一个巨大的耦合怪物。

=>不同意。在某些情况下,不同的应用程序仍然是同一单元的一部分,因此,在这种情况下,“耦合问题”的概念毫无意义。

让我们继续:Web应用程序处理客户端HTTP请求,并可能随时更新某些聚合(DDD术语),从而生成相应的域事件。
工作人员的目标是通过处理所需的作业来处理那些域事件。

重点是:

事件数据应如何传递给工作人员?

正如阅读的文章所提倡的那样,第一个解决方案是使用RabbitMQ,它是一款出色的面向消息的中间件。

工作流程将很简单:

每当Web dyno生成事件时,它都会通过RabbitMQ发布该事件,从而为工作人员提供帮助。
缺点是,如果不处理潜在的发送失败或硬件问题,则无法保证提交汇总更新和事件的发布之间的即时一致性。这是另一个主要问题。

示例:发布事件可能没有成功进行汇总更新...导致事件代表域模型的错误表示。
您可能会争辩说存在全局XA(两阶段提交),但这不是适合所有数据库或中间件的解决方案。

那么,什么是确保这种即时一致性的好的解决方案?:
IMO,将事件存储在数据库中,并且与聚合更新在同一本地事务中。
将创建一个简单的异步调度程序,并负责从数据库查询当前未发布的事件,并将其发送到RabbitMQ,后者再填充工作程序。

但是,为什么还要在webapp端并需要一个额外的调度程序:为什么在这种情况下需要RabbitMQ?

通过这种解决方案,在逻辑上似乎可以不需要RabbitMQ,尤其是因为数据库是共享的。
确实,无论如何,我们都看到即时一致性涉及从数据库进行轮询。
因此,为什么工人不直接对这次投票负责?

因此,我想知道为什么网络上有那么多文章在推广面向消息的中间件时几乎没有批评数据库排队。

文章摘录:

简单,使用正确的工具完成工作:这种情况正在引起消息传递系统的注意。它解决了上述所有问题;不再需要轮询,高效的消息传递,无需从队列中清除已完成的消息以及没有共享状态。

和即时的一致性,被忽略了吗?

综上所述,实际上无论情况如何,无论是否共享数据库,我们都需要数据库轮询

我错过了一些批评观念吗?

谢谢


2
轮询有点像是在鲱鱼,因为几乎所有的主要数据库都有某种机制可以异步通知其他进程,该是时候从表中提取一些工作了。
Blrfl 2014年

Answers:


28

如果您正在构建一个低流量的简单应用程序,那么对于将另一个组件保留在系统之外的话,您可以说些什么。不使用消息总线很可能是您的正确答案。但是,我建议您以一种可以将基于数据库的队列系统换成中间件解决方案的方式来构建系统。我同意这篇文章。数据库不是用于基于队列的系统的正确工具,但对您来说可能已经足够了。

像RabbitMq这样基于队列的系统是在中等硬件上大规模构建的。他们的体系结构能够通过避免因其性质而使符合ACID的数据库系统变慢的过程来实现这一目标。由于消息总线仅需要确保消息已存储并成功处理,因此无需费心锁定和写入事务日志。这两个概念对于ACID系统都是绝对必需的,但通常会引起争执。

从性能角度讲,它可以归结为:您有一个SQL表。大量的读取和大量的写入。两者都需要某种锁定来更新行,页面和索引。您的轮询机制会不断锁定索引以对其进行查询。这样可以防止发生写操作。充其量他们排队。进行处理的代码也被锁定以在队列完成或失败时更新队列上的状态。是的,您可以在优化后进行查询优化以使其正常工作,或者可以使用专门为您要求的工作量设计的系统。RabbitMq可以吃掉这种工作量,甚至不费吹灰之力。最重要的是,您可以从工作负载中保存数据库,从而为执行其他操作提供更大的扩展空间。

要考虑的另一件事是,大多数队列系统通常不使用轮询技术(有些允许使用HTTP,但建议避免将其用于接收端)。RabbitMq使用专门为消息总线设计的网络协议,例如AMPQ

编辑:添加用例。

我使用Rabbit的方式是我有一个API端点,该端点接受需要大量使用数据库表的更改。该表一直处于争用状态,有时无法及时从API保存更改。我要做的是将更改请求写入队列,然后有一个服务来处理这些消息。如果发生数据库争用,队列只会增加,消息处理也会延迟。通常,处理时间降低到14ms范围内,但是在竞争激烈的时候,我们最多可以提高2-3秒。


在这种情况下,您如何处理即时紧急情况?如果发布是在发布之后进行的,则负责更新域模型回滚的事务...中间件将完全不知道,并将处理该事件。
Mik378 2014年

您写道:“它不需要打扰”。但是,为了确保路由事件(朝工作人员)的升序(按时间顺序),肯定有一种锁定方式,对吗?
Mik378 2014年

@ Mik378看看这篇关于消息幂等的文章。是的,从技术上讲,您会失去一致性的保证,但是我敢打赌,您会发现从应用程序正常运行时间和性能方面获得的收益是值得的。改变处理消息的方式也很容易,以使丢失变得无痛。
brianfeucht 2014年

2
是的,您需要锁定才能保证订单。一些队列系统可以以性能为代价提供此功能。如果您可以接受有时操作会乱序并找出在处理器端进行处理的方法这一事实,那么从性能的角度来看,您将获得成倍的收益。
brianfeucht 2014年

1
@ Mik378-我在回答中添加了一个用例。希望对您有所帮助!
brianfeucht 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.