我试图了解 RabbitMQ 的最佳用途来满足以下问题。
作为上下文,我不关心此用例中的性能(此流的峰值 TPS 为 2 TPS),但我担心弹性。
我在集群中安装了 RabbitMQ 并忽略死信队列,基本流程是我有一个服务接收请求,创建一个持久消息,它在事务中排队到一个持久队列(此时我很高兴请求被保护到磁盘)。然后我让另一个进程侦听一条消息,它读取(不使用自动确认),做一堆事情,将一条新消息写入事务中的不同交换队列(现在再次高兴这条消息被保护到磁盘)。假设事务成功完成,它会手动将消息确认回原始消费者。
在这一点上,我唯一的失败情况是我在提交事务以写入我的第二个队列和返回 ack 之间失败。这将导致一条消息可能被处理两次。我还能做些什么来填补这个空白,或者我是否必须想出一种处理重复消息的方法。
作为上下文的最后一点,服务是用 java 编写的,因此使用 java 客户端库。
保罗·菲茨。
首先,我建议您在此处查看本指南,其中包含有关您的主题的大量有效信息。
来自 RabbitMQ 指南:
在制作人处
使用确认时,从通道或连接故障中恢复的生产者应重新传输尚未从代理收到确认的任何消息。这里存在消息重复的可能性,因为代理可能发送了从未到达生产者的确认(由于网络故障等)。因此,消费者应用程序需要以幂等方式执行重复数据删除或处理传入消息。
在消费者
在网络故障(或节点崩溃)的情况下,消息可以被复制,消费者必须准备好处理它们。如果可能,处理此问题的最简单方法是确保您的使用者以幂等方式处理消息,而不是显式处理重复数据删除。
因此,关键是根本不可能保证您的这种“失败”情况不会发生。您将始终必须处理网络故障、磁盘故障、将某些内容放在这里故障等。
您在这里要做的是依靠消息传递体系结构并实现消息的可能“幂等性”(这意味着即使您处理消息两次也不会发生任何错误,请检查此内容)。如果不能,则应提供某种“已处理消息”列表(例如,您可以在每条消息中使用 guid)并在每次收到消息时检查此列表;在这种情况下,您可以简单地丢弃它们。
为了更“理论化”,Brave New Geek 的这篇文章非常有趣:
在分布式系统的上下文中,您不能只进行一次消息传递。
希望能帮助到你 :)
归档时间: |
|
查看次数: |
2428 次 |
最近记录: |