Rabbitmq 跨队列的消息排序

Rabbitmq 跨队列的消息排序,rabbitmq,message-queue,distributed-computing,Rabbitmq,Message Queue,Distributed Computing,我的RabbitMQ设置中有一个场景,我很想知道如何解决。下图对此进行了说明(为了简洁起见,已删除了交换和大多数队列): 场景 生产者创建消息A(1),它由顶级消费者接收,后者开始处理消息 生产者创建消息A(2),由底层消费者接收(假设两个消费者都在循环交换中) 底部使用者发布消息B(2),该消息被放入消息B使用者的队列中 可怜的慢顶端消费者最终完成并发出其信息B(1) 问题 如果我们假设B消费者不能成为幂等的,我们如何确保两条B消息的结果都以正确的顺序应用 我曾想过使用一个应用于消息a的初始

我的RabbitMQ设置中有一个场景,我很想知道如何解决。下图对此进行了说明(为了简洁起见,已删除了交换和大多数队列):

场景

  • 生产者创建消息A(1),它由顶级消费者接收,后者开始处理消息
  • 生产者创建消息A(2),由底层消费者接收(假设两个消费者都在循环交换中)
  • 底部使用者发布消息B(2),该消息被放入消息B使用者的队列中
  • 可怜的慢顶端消费者最终完成并发出其信息B(1)
  • 问题

    如果我们假设B消费者不能成为幂等的,我们如何确保两条B消息的结果都以正确的顺序应用

    我曾想过使用一个应用于消息a的初始发布的时间戳,让消费者维护最后一次更改的时间戳,拒绝在该时间之前的任何时间戳,但只有当每条消息导致完全相同的更改并且需要大量跟踪时,这才有效


    对于如何处理这一问题的其他想法,我们将不胜感激。谢谢

    我不确定RabbitMQ在这里具体是什么,但是如果您只有一个生产者,那么使用时间戳的想法听起来是一个很好的开始

    生产者将时间戳附加到消息a,每个消息B采用其各自消息a的相同时间戳

    使用您的方法,某些消息不会被处理,例如消息B(1)。如果所有消息都应由使用者B处理,但它们应以确定性顺序处理,则您可以执行确定性合并:

    消费者B配备两个队列,每个消费者A对应一个队列。消费者B始终检查两个队列的顶部:

    • 如果两个队列都非空,消费者B将弹出时间戳最低的消息
    • 如果至少有一个队列为空,则使用者B等待
    使用这种方法,消费者B处理消息的顺序由生产者的时间戳给出,不丢弃任何消息。假设是:

    • 队列是先进先出的
    • 没有进程崩溃
    • 通常情况下,最终每个消费者都会处理一条消息
    • 消费者B可以以非阻塞方式检查队列顶部

    您的问题似乎与感谢这个非常有趣的想法有关。不幸的是,在我们的特殊情况下很难实现,因为我们无法保证假设3(最终每个消费者A产生一条消息)-上面的模型稍微简化了,消费者的数量可以动态扩展,因此,消费者B的队列必须与之同步扩展。这确实让事情变得更加困难。一些建议:(1)如果消费者A的集合是固定的,但它们有时是沉默的(不发送消息),您可以通过周期性地让生产者心跳并迫使消费者下游控制消息来解决这一问题,只是为了填充消费者B中的队列。(2)如果消费者A的集合发生变化,这个答案的方法要求您在某个地方保持一致的成员集,例如,在制作人本身或ZooKeeper集合中。必须通知消费者B哪一组消费者A在哪个时间戳之前处于活动状态。同样,从生产者到消费者B的心跳可以携带这样的成员资格和时间戳信息。(3) 关于扩展B中的队列:B仍然可以有一个输入队列,只需为从输入队列中退出队列但尚未处理的消息保留一组内部缓冲区。在我看来,唯一可行的解决方案是创建一个聚合器,它将聚合和重新排序消息B(X)。聚合器应由数据存储(内存和/或磁盘,如redis、rdbms)支持。为了能够聚合和重新排序消息,标识符(UUID)、顺序和计数应该与消息A(X)相关联。聚合器将向消费者B发布消息B(X),并保证订购