RabbitMQ队列中消息恢复的最佳实践

时间:2016-04-27 15:45:08

标签: java rabbitmq

我试图了解RabbitMQ的最佳用途,以满足以下问题。

由于上下文我不关心此用例的性能(此流量的峰值TPS为2 TPS),但我担心恢复能力。

我将RabbitMQ安装在集群中并忽略死信队列基本流程是我有一个服务接收请求,创建一个持久消息,它在事务中排队到一个持久队列(此时我&#39 ;很高兴请求被保护到磁盘)。然后我有另一个进程正在侦听一条消息,它读取(不使用auto ack),做了很多事情,将一条新消息写入事务中的另一个交换队列(现在再次感到高兴的是这条消息被保护到磁盘)。假设事务成功完成,它会手动将消息回送给原始使用者。

此时我唯一的失败场景是我在提交事务以写入第二个队列和返回ack之间出现故障。这将导致消息可能被处理两次。我还能做些什么来填补这个空白,或者我必须想办法处理重复的消息。

作为上下文的最后一点,服务是用java编写的,所以使用java客户端库。

保罗菲茨。

1 个答案:

答案 0 :(得分:2)

首先,我建议您查看本指南here,其中包含有关您主题的大量有效信息。

来自RabbitMQ指南:

在制片人

  

使用确认时,生产者从频道或连接中恢复   失败应重新传输任何确认的消息   尚未收到经纪人的通知。有可能   消息重复在这里,因为经纪人可能已经发送了一个   从未到达生产者的确认(由于网络故障,   等等)。 因此消费者应用程序需要执行   重复数据删除或以幂等方式处理传入的消息。

消费者

  

如果网络出现故障(或节点崩溃),可以发送消息   重复,消费者必须准备好处理它们。 如果   可能,最简单的方法是确保你的   消费者以幂等方式处理消息而不是明确地处理消息   处理重复数据删除

所以,重点是不可能以任何方式保证你的“失败”情况不会发生。您将始终必须处理网络故障,磁盘故障,在此处放置故障等。

您需要做的是依靠消息传递架构并实现您的消息的“ idempotency ”(这意味着即使您处理消息两次也不会发生任何事情)错了,检查this)。 如果您不能提供某种“已处理的消息”列表(例如,您可以在每条消息中使用guid)并在每次收到消息时检查此列表;在这种情况下你可以简单地丢弃它们。

为了更加“理论化”,来自Brave New Geek的this帖子非常有趣:

  

在分布式系统的环境中,你不能拥有   准确的一次消息传递。

希望有所帮助:)