【问题标题】:How to guarantee message order in RabbitMQ (or any other asynchronous message queue service)如何保证 RabbitMQ(或任何其他异步消息队列服务)中的消息顺序
【发布时间】:2019-04-25 12:14:14
【问题描述】:

我有一个将事件发布到 RabbitMQ 的 Java 应用程序。它有一个非常重要的特性:必须始终保持消息顺序。消费者可以处理重复,但是当消息2在消息1之前入队时它不能处理,可以这么说。

我最近读了很多关于 RabbitMQ 的文章,我觉得只有解决方案:将频道设置为confirm 模式(https://www.rabbitmq.com/confirms.html - 基本上,它强制代理确认发布)并发布逐个。我的意思是,消息 2 仅在 RabbitMQ 确认(通过异步 ACK 响应)消息 1 实际上被良好接收和持久化后才发布。

我在概念实现中尝试过这个,虽然效果很好,但速度非常慢,一点也不夸张。这是有道理的:毕竟,我们现在将消息速率限制为一次 1 条消息。

所以这引出了我的问题:是否有其他更高效的方法来确保始终保留消息排序(在 RabbitMQ 中或通过不同的方法)?

虽然我关心的是 RabbitMQ,但我相信这个问题可能适用于任何类型的异步消息队列服务。

【问题讨论】:

    标签: rabbitmq message-queue


    【解决方案1】:

    RabbitMQ 的客户端按照您发送的顺序排入队列。当订阅者出现故障时,您会收到网络分裂或订阅者 NACK 消息,他们可以重新排序;即使这样 RMQ 也会尝试通过在相同位置重新排队或尽可能接近相同位置来保持它们大致相同的顺序。

    你可以按照你的建议去做; 一次接收一条消息,因为如果你接收一条消息,但在你从代理确认它之前崩溃了,它会在你的服务恢复时弹出,在相同的位置。

    这假设您在任何给定时间只有一个单个服务实例,从队列中消费。如果您有像 Kubernetes 或 Mesos 这样的调度程序来生成服务实例,那么这本身就是一个分布式系统问题。

    另一种解决方案是确保接收服务中的处理顺序,方法是根据消息的逻辑时间戳/序列号“重新排序”消息。

    我在这里https://github.com/haf/rmq-publisher-confirms-hopac/blob/master/src/Server/Shared/RabbitMQ.fs 写了一个更详尽的指南作为注释代码——通过批处理,您可以重新排序。此外,如果您的幂等性将连续序列号构建到其逻辑中,您就可以开始批量处理,并且每个事件都将是幂等的,尽管被重新消费。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-01
      • 2019-11-04
      • 1970-01-01
      • 2019-05-04
      • 2013-08-09
      • 2015-08-22
      • 2020-08-31
      相关资源
      最近更新 更多