RabbitMQ 集群和镜像队列的幕后行为

标签 rabbitmq haproxy high-availability

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

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

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

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

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

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

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

最佳答案

Can someone please explain what is going on behind the scenes in a RabbitMQ cluster with multiple nodes and queues in mirrored fashion when publishing to a slave node?



This博客概述了到底发生了什么。

But what happens when I publish to a slave node? Will this node do the same thing of sending first the message to the master?



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

But how do you handle master failure? Then one of the slaves will be elected master, so you have to know where to connect to?



再次,这是涵盖 here .本质上,您需要一个单独的服务来轮询 RabbitMQ 并确定节点是否处于事件状态。 RabbitMQ 提供了一个 management API为此。您的发布和消费应用程序需要直接或通过相互数据存储引用此服务,以确定要向其发布或消费的正确节点。

The connection to rabbit is permanent, so if it fails, you have to recreate it. Also, you have to resend the messages in this cases, otherwise you will lose them.



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

Even with all of this, messages can still be lost, because they may be in transit when I kill a node



有些边缘情况您不能用冗余覆盖,RabbitMQ 也不能。例如,当消息进入队列时,HA 策略调用后台进程将消息复制到备份节点。在此过程中,消息在持久化到备份节点之前可能会丢失。如果主动节点立即发生故障,消息将永远丢失。对此没有什么可以做的。不幸的是,当我们深入到在线传输的实际字节级别时,我们可以构建的保护措施的数量是有限的。

herefore consumer applications will need to perform deduplication or handle incoming messages in an idempotent manner.



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

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

关于RabbitMQ 集群和镜像队列的幕后行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27104726/

相关文章:

ruby - RabbitMQ Bunny 并行消费者

hadoop - 在 hadoop 中获取名称服务的事件名称节点的任何命令?

database - 具有幂等增长运算符的最终一致性分布式数据库?

java - 如何让多个客户倾听同一消费者的声音?

rabbitmq ReturnCallback 在 NO_ROUTE(312) 上声明队列时卡住

java - RabbitMQ,如何在 n 次重新排队尝试后删除消息

web-services - 适合新手的实用 SOA

mariadb - MariaDB 和 HAProxy(集群)的连接问题

HAProxy - use_backend 如果可用

linux - Haproxy 无法绑定(bind) [0.0.0.0 :80] - CentOS 6. 5