我有一个RabbitMQ消息结构,消息A
应该生成大量消息,让我们称之为B
和C
。工作进程收到消息A
,然后处理该消息并生成消息B
和C
。
假设的工作流程如下:
A
ack=False
B
C
ack
邮件A
在任何情况下,工作进程在处理消息A
期间死亡,或者当尚未完成事务时 - 我希望RabbitMQ将消息A
视为未传递并重新排队它
如果相关,RabbitMQ将以高可用性配置运行。
为什么问题是尝试清除RabbitMQ文档here,说明:
此外,即使在仅涉及单个队列的事务的情况下,RabbitMQ也不提供原子性保证,例如,在tx.commit期间发生的故障可能导致在代理重启后,事务的发布子集出现在队列中。
答案 0 :(得分:0)
您需要相当多的基础架构(代码)才能使其正常工作。这很棘手。
您可能需要考虑服务总线。我在这里有一个免费的.net开源软件:http://shuttle.github.io/shuttle-esb/
如果您不在.net空间或对使用服务总线不感兴趣,您可以按照一些代码查看Shuttle.Esb如何处理这些事情:https://github.com/Shuttle/Shuttle.Esb
您可能还想查看此处IdempotenceService
:https://github.com/Shuttle/Shuttle.Esb.SqlServer/blob/master/Shuttle.ESB.SqlServer/Idempotence/IdempotenceService.cs
当使用idempotence服务器(在处理程序中)时,所有已发送的消息都存储在事务存储中(在本例中类似于sql server),并且仅在消息处理成功完成后发送。
对于在消息处理程序之外发送,可以使用事务发件箱(同样,基于sql server表的队列也可以工作)。
关键是你需要对你的设计进行一些认真思考,这将会很棘手。
答案 1 :(得分:0)
我在定位最流行的产品时犯了一个错误,就像在我看来一样。 ActiveMQ完全支持高可用性和事务,所以我刚刚切换到那里,我的问题就消失了。
答案 2 :(得分:0)
我们有一些系统在生产中完全像这样工作,其基本格式为:
如果步骤#2失败,则消息A被重新排队"并且可以再次拿起。
当消息发送到队列并成功接收时,该消息将标记为ready
。当它被发送给消费者时,它被标记为unacked
,直到被所述消费者确认它被从队列中移除。
在您的示例中,在您确认步骤#6中的消息之前,它仍然处于unacked
状态,这意味着如果工作进程在步骤#6之前死亡,则消息将会滑回到 RabbitMQ 中的ready
状态,准备发送给另一个工作人员。
此功能确实依赖于您未明确禁用确认的事实。如果您是,我非常确定邮件会在发送给消费者后立即从队列中删除。