我有一个针对RabbitMQ的特定用例,我想澄清某些事情并寻求建议。
考虑这种情况:
1-我发布了两条消息,即要执行的任务:messageA,然后是messageB
2-我的消费者获取messageA,执行此消息中包含的任务,但在任务运行时,服务器崩溃
我的问题是:当服务器重新启动时,messageA是否会被重新排队,并且会在messageB之前重新排队(与崩溃前的顺序相同)?
根据我的理解,如果服务器崩溃,messageA将会丢失,因为我的消费者在接收到消息后默认已经确认了它。
所以我的想法是分别使用和确认消息:首先消耗,运行任务,然后在任务成功执行时确认消息。
你觉得这种方法有问题吗?你能建议我做别的吗?
答案 0 :(得分:1)
RabbitMQ不会保留重新排队的消息顺序:
在大多数情况下,是的。假设发布者发布消息M1,M2,M3 和M4(按此顺序)在同一个通道上并具有相同的路由 信息。如果这些消息被路由到队列,那么他们将 最终按照他们发布的顺序排列。消费在 队列将产生M1,M2,M3,然后产生M4。
但是,只有在没有重新排队的情况下才会保证订单。一个 如果消费者关闭频道,则消息将被隐式重新排队 在收到消息之前例如,如果消费者收到M1, 没有确认和关闭频道然后下一个消费者将 按M2,M3,M4,M1的顺序接收消息。消息也可以 如果消费者调用basic.recover {requeue = true},则显式重新排队。 关于至少一次交付的常见问题解答还有更多内容 细节。
这可以完成,但RabbitMQ不会自动完成,您需要通过将子消息包装在父消息中来自行管理生命周期。然后,如果消息1成功但消息2失败,您将拥有管理父消息和处理回滚的代码。希望这有助于..
最好的问候
答案 1 :(得分:0)
在no-ack模式下消耗的消息(请参阅http://www.rabbitmq.com/amqp-0-9-1-reference.html#domain.no-ack)在服务器崩溃后不会被重新排队,因为服务器在交付时完全忘记了这些消息。消费者在交付后对此类消息负责。
仅在成功完成任务后确认消息才是您方案中的正确方法。如果您希望消息在代理崩溃后继续存在,那么您还必须确保该队列是持久的并且消息是持久发布的(交付模式2),并且发布者确认或事务用于确保将消息写入磁盘
如果代理在处理messageA时崩溃,则将保留消息顺序。如果消费者而不是经纪人崩溃,那么消息顺序将被颠倒。