我认为在这种情况下不需要重新排序器。如果您需要确保按特定顺序删除项目,也许是这样。但这只有在您大致同时发送多条消息并且需要保证消费者端的顺序时才会发挥作用。
由于您提到的原因,您还应该避免超时情况。 timeout 是为了告诉 RabbitMQ 一条消息不需要被处理——或者它需要被路由到一个死信队列,以便我可以被其他一些代码处理。虽然您可以让超时工作,但我认为这不是一个好的选择。
优先级可能会解决部分问题,但可能会引入文件永远不会被处理的情况。如果您将优先级 1 的消息放回队列中的某个位置,并且您继续将优先级 2、3、5、10 等放入队列,则可能不会处理 1。正如您所指出的,超时并不能解决这个问题。
为了我的钱,我会建议一种不同的方法:为单个文件串行发送删除请求。
即发送1条消息删除1个文件。等待回复说它已经完成。然后发送下一条消息以删除下一个文件。
这就是我认为这会起作用的原因,以及如何管理它:
长时间运行的工作流程,单个文件删除请求
在这种情况下,我建议使用“传奇”(又名a long-running workflow object)的想法采取多步骤方法来解决问题。
当用户请求删除他们的垃圾箱时,您通过 rabbitmq 向可以处理删除过程的服务发送一条消息。该服务会为该用户的垃圾桶创建一个 saga 实例。
传奇收集了垃圾箱中需要删除的所有文件的列表。然后它开始发送删除单个文件的请求,一次一个。
对于删除单个文件的每个请求,saga 都会等待响应说文件已被删除。
当 saga 收到上一个文件已被删除的消息时,它会发出下一个删除下一个文件的请求。
一旦所有文件都被删除,saga 会更新自己和系统的任何其他部分,说垃圾桶是空的。
处理多个用户
当您有一个用户请求删除时,对他们来说事情会很快发生。他们很快就会清空垃圾。
u1 = 用户 1 垃圾箱删除请求
|u1|u1|u1|u1|u1|u1|u1|u1|u1|u1完成|
当您有多个用户请求删除时,一次发送一个文件删除请求的过程意味着每个用户将有相同的机会获得下一个文件删除。
u1 = 用户 1 垃圾箱删除请求
u2 = 用户 2 垃圾箱删除请求
|u1|u2|u1|u1|u2|u2|u1|u2|u1|u2|u2|u1|u1|u1|u2|u2|u1|u2|u1|u1done|u2|u2done|
这样,将共享使用资源来删除文件。总体而言,清空每个人的垃圾桶需要更长的时间,但他们会更快看到进展,这是人们认为系统快速/响应他们的请求的一个重要方面。
优化小文件集与大文件集
在用户数量较少且文件数量较少的情况下,上述解决方案可能会比一次性删除所有文件要慢。毕竟,通过rabbitmq发送的消息会更多——每个需要删除的文件至少有2条消息(一个删除请求,一个删除确认响应)
要进一步优化,您可以做几件事:
在像这样拆分工作之前,有一个最小的垃圾桶大小。低于最低限度,您只需一次将其全部删除
将工作分成几组文件,而不是一次一个。也许 10 或 100 个文件会比一次 1 个文件更好的组大小
这些解决方案中的任何一个(或两个)都可以通过减少发送的消息数量和稍微分批处理工作来帮助提高流程的整体性能。
您需要在真实场景中进行一些测试,以了解其中哪些(或可能两者兼有)会有所帮助以及在什么设置下会有所帮助。
多用户问题
还有一个您可能面临的额外问题 - 许多用户。如果您有 2 或 3 个用户请求删除,这没什么大不了的。
但是,如果您有 100 或 1000 个用户请求删除,则个人可能需要很长时间才能清空他们的垃圾桶。
对于这种情况,您可能需要一个更高级别的控制流程,所有清空垃圾桶的请求都将由另一个 Saga 管理。这个 saga 会限制活跃的垃圾桶删除 sagas 的数量。
例如,如果您有 10 个删除垃圾箱的活动请求,则限速 saga 只会启动其中的 3 个,并且会等待其中一个完成,然后再开始下一个。
同样,出于性能原因,您需要测试您的实际场景以查看是否需要这样做,并查看应该有哪些限制。
在您的实际场景中可能需要考虑其他场景,但我希望这能让您走上正轨! :)