消息传送顺序
我需要为我的新项目选择一个新的队列代理。
这次我需要一个支持pub / sub的可扩展队列,并且保持消息排序是必须的。
我读亚历克西斯评论:他写道:
“的确,我们认为RabbitMQ比Kafka提供更强的订购”
我阅读rabbitmq文档中的消息排序部分:
“使用AMQP方法可以将消息返回到队列中,这些方法具有一个requeue参数(basic.recover,basic.reject和basic.nack),或者由于频道关闭时保持未确认的消息...使用2.7.0及更高版本如果队列中有多个用户,那么个人用户仍然可能会观察到消息乱序,这是由于其他用户可能需要消息的行为所致,从队列的角度来看,消息总是保持在发布顺序中。 “
如果我需要通过他们的订单来处理消息,那么我只能使用rabbitMQ为每个消费者提供排队队列?
RabbitMQ仍然被认为是有序消息排队的好方案吗?
那么,让我们仔细看看你上面描述的场景。 我认为在问题片段之前立即粘贴文档以提供上下文很重要:
AMQP 0-9-1核心规范的第4.7节解释了保证排序的条件:在一个频道中发布的消息,通过一个交换机,一个队列和一个输出频道将按照它们发送的相同顺序接收。 自2.7.0版本以来,RabbitMQ提供了更强大的保证。
使用AMQP方法可以将消息返回到队列,这些方法具有一个requeue参数(basic.recover,basic.reject和basic.nack),或者由于在保存未确认消息时关闭通道。 任何这些情况都会导致消息在队列的后端重新排队,以便早于2.7.0的RabbitMQ版本发布。 从RabbitMQ版本2.7.0开始,消息始终以发布顺序保存在队列中,即使存在重新发送或通道关闭时也是如此。 (强调加)
所以,显然,从2.7.0开始,RabbitMQ对于原始AMQP规范在消息排序方面做出了相当大的改进。
对于多个(并行)消费者,处理顺序不能得到保证。
第三段(粘贴在问题中)接着给出了一个免责声明,我将其解释为:“如果队列中有多个处理器,则不再保证消息将按顺序处理。” 他们在这里所说的是RabbitMQ不能违抗数学规律。
考虑银行的一系列客户。 这家银行以他们进入银行的顺序帮助客户而自豪。 顾客排队等候,并由3个可用出纳员中的下一个出纳员服务。
今天早上,所有三名出纳员同时可用,接下来的三名顾客接近。 突然之间,三名出纳员中的第一位病情变得严重,并且无法完成为该行的第一位顾客提供服务。 到此为止,柜员2已经结束了客户2,柜员3已经开始为客户3服务。
现在,可能会发生以下两件事之一。 (1)在线的第一个客户可以返回到线路的头部,或者(2)第一个客户可以抢先占用第三个客户,导致该出纳员停止在第三个客户上工作并开始第一个客户的工作。 RabbitMQ不支持这种类型的占先逻辑,也不支持我知道的任何其他消息代理。 在任何一种情况下,第一位顾客实际上并没有最终得到帮助 - 第二位顾客确实很幸运,他们很幸运能够找到一位优秀的快速出纳员。 保证顾客得到帮助的唯一方法是让一位柜员一次帮助顾客,这将给银行带来重大的客户服务问题。
我希望这有助于说明你所问的问题。 考虑到你有多个消费者,不可能确保消息在每种可能的情况下都按顺序处理。 不管你是否有多个队列,多个独占消费者,不同的经纪人等等, - 没有办法保证先验信息是按照多个消费者的顺序来回答的。 但RabbitMQ将尽最大努力。
消息排序被保留在Kafka中,但仅限于分区而不是全局分区。 如果你的数据需要全局排序和分区,这确实会让事情变得困难。 但是,如果您只需确保同一用户的所有相同事件等最终都在同一个分区中,以便它们得到正确排序,则可以这样做。 生产者负责他们写入的分区,所以如果你能够在逻辑上对数据进行分区,这可能更可取。
我认为在这个问题中有两个不相似的东西,消费订单和处理顺序。
消息队列可以在一定程度上给你一个保证消息按顺序被消费的保证,但是它们不能为你的处理顺序提供任何保证。
这里的主要区别在于消息处理的某些方面不能在消费时间确定,例如:
如前所述,消费者在处理时可能会失败,这里消息的消费顺序是正确的,但消费者未能正确处理它,这将使其返回队列,直到现在消费订单仍然完好无损,不知道现在的处理顺序如何
如果通过“处理”我们的意思是消息现在被丢弃并完成处理,那么考虑处理时间不是线性的情况,换句话说,处理一条消息需要比另一条更长的时间,所以如果消息3处理时间比预计,那么消息4和消息5可能会消耗并在消息3之前完成处理
因此,即使您设法将邮件恢复到队列的前端(顺便违反了使用顺序),仍然无法保证下一条邮件之前的所有邮件都已完成处理。
如果你想确保处理顺序,那么:
上一篇: Message order of delivery
下一篇: RabbitMQ and relationship between channel and connection