RabbitMQ - 如何确保两个队列保持同步

时间:2017-11-29 15:08:58

标签: rabbitmq queue message-queue

我有两个队列,它们都有不同的数据类型,这些数据类型会因我的应用程序正在处理而相互影响,因此异步处理来自这两个队列的消息会导致数据完整性问题。

我很好奇确保只有一个消费者在任何特定时间消费的最佳做法。以下是我到目前为止的总结:

EventMessages会收到有关可能会或可能不会对排队/现有PurchaseOrderMessages产生影响的外部事件的信息。

由于我们预计我们会比PurchaseOrderMessage消耗更多EventMessage,因此在我们处理任何内容之前,我们应该确保EventMessage队列为空(通过API) PurchaseOrderMessage队列 - 但这会产生等待时间等问题,而这一切都需要尽可能接近实时发生。

如果有一种方法可以简单地暂停消费者A,直到消费者B处于静止状态,这可能是最简单的解决方案,我只是不确定我需要哪个方向进去。

更新

要提供一些额外的上下文,PurchaseOrderMessage将包含Origin和Destination。

EventMessage也包含位置数据。

每次处理PurchaseOrderMessage时,它都会查询当前EventMessage个记录,查找与该Event的来源和目标匹配的任何PurchaseOrder个位置,并创建关联

每次处理EventMessage时,它都会查询当前PurchaseOrderMessage条记录中与Event匹配的任何目的地来源并创建关联。

如果同步队列不是一个好的解决方案,那么当EventMessagesPurchaseOrderMessages发布到应用程序时,可以确保不会错过任何关联。同一时间?

更新2

最终,此数据将提供一个用户界面,其中包含PurchaseOrders列表以及可能影响其投放日期的事件。进行"事件检查"会太慢。因为最终用户正在呈现/检索PurchaseOrder数据,这就是我们为什么要在处理/消费时进行处理的原因。

1 个答案:

答案 0 :(得分:4)

让我从前面的底线开始 - 面对它的,你所要求的是没有意义的。

队列永远不需要同步。 这样做的想法完全违背了排队的目的。对于某些背景,请访问this answer

让我们考虑现实生活中遇到多个队列的一些常见地方:

  1. 电影院(票房,特许柜台,迎来)
  2. 主题公园(小吃店,主要景点)
  3. 制造地板(每个工作站可能有一个等待处理的队列)
  4. 在每个示例中,从队列中对象的角度来看,它只能一次一个地等待。当它在另一行等待时,它不能在一行中等待 - 这样的事情在物理上是不可能的。

    你的例子似乎采取了两个完全不相关的东西并将它们合并在一起。您有PurchaseOrder个对象的队列 - 但队列是什么?这相当于去迪士尼世界并在Customer队列中等待 - 这样一个队列的目的是什么?如果目的不明确,那就不是真正的队列。

    解决您的问题

    首先需要通过明确定义正在对PurchaseOrder执行的各种操作,然后为每个操作创建队列来解决此特定问题。如果这些操作是真正同步的,那么应该对业务逻辑进行编码,以等待一个操作完成,然后再启动另一个操作。在这种情况下,如果PurchaseOrder在没有满足先决条件的情况下到达一个队列的头部,则会被视为例外。

    请记住,消息队列通常用于无状态操作。良好的设计要求队列中的消息包含处理器处理消息所需的所有信息。如果你不遵守这一点,那么你的数据库就会成为你系统的一个争用点 - 虽然这不是一个不可克服的问题,但它确实会使设计变得更加复杂。

    等待多个队列

    现在,如果您曾经去过迪斯尼世界,您也会知道他们有一个名为FastPass+ (FP+)的东西,允许持有者跳过指定景点的线。迪士尼每小时为公园的每个主要景点分配一定数量的插槽,并且客人每天可以请求最多三个FP +。 FP +时间分配为一小时块,并且客人不能有两个重叠的FP +时间块。一旦为骑行发出所有FP +插槽,就不再提供。 FP +系统确保强制执行这些规则,而与每次乘坐的备用队列无关。基本上,通过使用FastPass +,客人可以在虚拟多行中等待,并在访问期间体验更多景点。

    如果您无法分析您的设计并提出替代方案,那么FastPass +方法可能有助于缓解一些瓶颈。

    免责声明:我不为迪士尼工作,但我每个月都会去多次,总是首先获得我的FastPass