Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何保证RabbitMQ(或任何其他异步消息队列服务)中的消息顺序_Rabbitmq_Message Queue - Fatal编程技术网

如何保证RabbitMQ(或任何其他异步消息队列服务)中的消息顺序

如何保证RabbitMQ(或任何其他异步消息队列服务)中的消息顺序,rabbitmq,message-queue,Rabbitmq,Message Queue,我有一个Java应用程序,它将事件发布到RabbitMQ。它有一个非常重要的特征:必须始终保持消息顺序。消费者可以处理重复项,但也就是说,当消息2在消息1之前排队时,消费者无法处理 最近我读了很多关于RabbitMQ的文章,我觉得只有一个解决方案可以做到这一点:将通道设置为confirm模式(-基本上,它强制代理确认发布)并逐个发布。我的意思是,消息2只有在RabbitMQ确认(通过异步ACK响应)消息1实际上已被很好地接收和持久化后才会发布 我在一个概念性的实现中尝试了这一点,虽然效果很好,但

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

最近我读了很多关于RabbitMQ的文章,我觉得只有一个解决方案可以做到这一点:将通道设置为
confirm
模式(-基本上,它强制代理确认发布)并逐个发布。我的意思是,消息
2
只有在RabbitMQ确认(通过异步
ACK
响应)消息
1
实际上已被很好地接收和持久化后才会发布

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

因此,这就引出了我的问题:是否有其他更高效的方法来确保始终保持消息顺序(在RabbitMQ中或通过不同的方法)


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

RabbitMQ的客户端按照您发送的相同顺序排队。当用户宕机时,您会收到网络拆分或用户NACKs消息,他们可以重新订购;即使如此,RMQ也会尝试通过在相同位置重新排队,或尽可能靠近相同位置,使它们保持相同的近似顺序

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

这假设您在任何给定时间只有一个单个服务实例,从队列中消耗。如果您有Kubernetes或Mesos之类的调度器,那么这本身就是一个分布式系统问题,会产生您的服务实例

另一个解决方案是,通过基于消息的逻辑时间戳/序列号对消息进行“重新排序”,确保接收服务中的处理顺序


我在这里编写了一个更全面的指南,作为带注释的代码-通过批处理,您可以重新排序。此外,如果您的幂等性将连续序列号构建到其逻辑中,则可以开始进行批处理,并且每个事件都将是幂等的,尽管它们被重新消费。

RabbitMQ的客户端将按照您发送的相同顺序排队。。当用户宕机时,您会收到网络拆分或用户NACKs消息,他们可以重新订购;即使如此,RMQ也会尝试通过在相同位置重新排队,或尽可能靠近相同位置,使它们保持相同的近似顺序

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

这假设您在任何给定时间只有一个单个服务实例,从队列中消耗。如果您有Kubernetes或Mesos之类的调度器,那么这本身就是一个分布式系统问题,会产生您的服务实例

另一个解决方案是,通过基于消息的逻辑时间戳/序列号对消息进行“重新排序”,确保接收服务中的处理顺序

我在这里编写了一个更全面的指南,作为带注释的代码-通过批处理,您可以重新排序。此外,如果您的幂等性将连续序列号构建到其逻辑中,那么您可以开始进行批处理,并且每个事件都将是幂等的,尽管它们被重新消费