【问题标题】:RabbitMQ clustering and mirror queues behavior behind the scenes幕后的 RabbitMQ 集群和镜像队列行为
【发布时间】:2014-11-26 01:43:51
【问题描述】:

有人可以解释一下在发布到从节点时,具有多个节点和队列的 RabbitMQ 集群的幕后情况吗?

根据我的阅读,似乎除了发布之外的所有操作都只发送给主服务器,然后主服务器将操作的效果广播给从服务器(这是来自文档)。根据我的理解,这意味着消费者将始终使用主队列中的消息。此外,如果我向从站发送请求以使用消息,则从站将通过到达主站获取该消息来进行额外的跳跃。

但是当我发布到从节点时会发生什么?这个节点会做同样的事情,首先将消息发送给主节点吗?

在处理slave时似乎有很多额外的hop,所以如果你只知道master,似乎你的性能会更好。但是你如何处理主失败?那么其中一个slave将被选为master,所以你必须知道连接到哪里?

问这一切是因为我们在前面使用带有 HAProxy 的 RabbitMQ 集群,因此我们可以将集群结构与我们的应用程序解耦。这样,每当一个节点完成时,HAProxy 都会重定向到活节点。但是当我们杀死其中一个兔子节点时,我们遇到了问题。与 rabbit 的连接是永久性的,因此如果失败,您必须重新创建它。此外,在这种情况下,您必须重新发送消息,否则您将丢失它们。

即使所有这些,消息仍然可能丢失,因为当我杀死一个节点时它们可能正在传输中(在某些缓冲区,网络上的某个地方等)。所以你必须使用事务或发布者确认,它保证在所有镜像都被消息填满后交付。但这里有另一个问题。您可能有重复的消息,因为代理可能发送了从未到达生产者的确认(由于网络故障等)。因此,消费者应用程序将需要执行重复数据删除或以幂等方式处理传入消息。

有没有办法避免这种情况?或者我必须决定是否可以丢失几条消息还是重复一些消息?

【问题讨论】:

    标签: rabbitmq haproxy high-availability


    【解决方案1】:

    有人可以解释一下在发布到从节点时,具有多个节点和队列的 RabbitMQ 集群的幕后情况吗?

    This 博客准确地概述了发生的事情。

    但是当我发布到从节点时会发生什么?这个节点会做同样的事情,首先将消息发送给主节点吗?

    消息将被重定向到主队列 - 即创建队列的节点。

    但是您如何处理主故障?那么其中一个slave将被选为master,所以你必须知道连接到哪里?

    同样,这已涵盖here。本质上,您需要一个单独的服务来轮询 RabbitMQ 并确定节点是否处于活动状态。 RabbitMQ 为此提供了management API。您的发布和消费应用程序需要直接引用此服务,或者通过相互数据存储来确定要发布到或从中消费的正确节点。

    与 rabbit 的连接是永久的,因此如果失败,您必须重新创建它。此外,在这种情况下,您必须重新发送消息,否则您将丢失它们。

    您需要订阅连接中断事件才能对断开的连接做出反应。您需要在客户端上建立某种程度的冗余,以确保消息不会丢失。如上所述,我建议您引入专门用于询问 RabbitMQ 的服务。您的客户端可以尝试将消息发布到最后一个已知的活动连接,如果此操作失败,客户端可能会要求监控服务提供 RabbitMQ 集群的最新列表。假设至少有一个活动节点,客户端就可以与它建立连接并成功发布消息。

    即使所有这些,消息仍然会丢失,因为当我杀死一个节点时它们可能正在传输中

    有些边缘情况是你无法用冗余覆盖的,RabbitMQ 也不能。例如,当消息进入队列时,HA 策略会调用后台进程将消息复制到备份节点。在此过程中,消息有可能在保存到备份节点之前丢失。如果活动节点立即失败,则消息将永远丢失。对此无能为力。不幸的是,当我们降低到通过网络传输的实际字节级别时,我们可以构建的保护措施数量是有限的。

    因此,消费者应用程序需要执行重复数据删除或以幂等方式处理传入消息。

    您可以通过多种方式处理此问题。例如,将message-ttl 设置为相对较低的值将确保重复的消息不会长时间保留在队列中。您还可以使用唯一引用标记每条消息,并在消费者级别检查该引用。当然,这需要存储已处理消息的缓存以比较传入消息;这个想法是,如果一个先前处理的消息到达,它的标签将被消费者缓存,并且可以忽略该消息。

    对于 AMQP 和基于队列的解决方案,我一般要强调的一件事是,您的基础架构提供了工具,而不是整个解决方案。您必须根据您的业务需求弥合这些差距。通常,最好的解决方案是通过反复试验得出的。希望我的建议有用。我在这里写了一些 RabbitMQ 设计解决方案的博客,包括你提到的问题,here如果你有兴趣。

    【讨论】:

    • 谢谢保罗。你是神。只是为了确保在我开始实施之前,请您确认一下:1)我仍然可以使用 HAProxy 和发布者确认,我不会丢失任何消息。我会有重复的消息,我必须以某种方式将其删除。我会遇到性能问题(由于第一次到达从属服务器时主服务器有额外的跃点),但我的数据将是“防弹的”。 2)为了提高性能,我会创建一个监控服务,所以我每次只向主服务器发送我的请求,但我仍然需要处理重复。谢谢。
    • 您仍然可以使用 HAProxy,但使​​用循环配置会产生额外的网络跃点。如果您想实现负载平衡,请阅读以下内容:insidethecpu.com/2014/11/17/load-balancing-a-rabbitmq-cluster 您不太可能有重复的消息。我认为设置 message-ttl 属性足以删除重复项,尽管正如我所提到的,添加一个引用标记将解决问题。我将很快发布一个用 C# 实现上述所有功能的 RabbitMQ 库。继续关注我的博客以获取更新。
    • 实际上我确实收到了重复的消息。我运行了几次测试,将 10000 条消息发布到 2 节点 Rabbit 集群。我杀死了一个节点,我收到了 10011-10012 条消息。我的一个消费 API 是幂等的,所以最终结果是好的。非常感谢。
    • 这很有趣,值得研究。不客气。
    猜你喜欢
    • 1970-01-01
    • 2018-04-28
    • 2014-05-21
    • 1970-01-01
    • 2012-05-14
    • 2018-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多