【问题标题】:Really durable queue in RabbitMQRabbitMQ 中真正持久的队列
【发布时间】:2023-06-20 01:37:01
【问题描述】:

我检查了RabbitMQ tutorial 的“消息持久性”部分。但它有这个注释:

将消息标记为持久性并不能完全保证消息 不会丢失。虽然它告诉 RabbitMQ 将消息保存到磁盘, 当 RabbitMQ 接受一个 消息,尚未保存。此外,RabbitMQ 不执行 fsync(2) 对于每条消息——它可能只是保存到缓存中而不是真的 写入磁盘

但是如果我需要真的持久队列怎么办?我可以使用哪些最佳实践? 例如,如果消息在 2 分钟内没有被确认,我是否应该在数据库中有“队列”并通过 cron 进行一些“重新发送”?有没有更好的解决方案?

另外,如果我的消费者在它处理消息之后和它发送 ACK 之前崩溃了怎么办?

UPD:我的问题被标记为集群问题的“可能重复”。我不知道集群如何帮助解决这些问题。

【问题讨论】:

  • 如果整个集群崩溃了怎么办?
  • 可能性非常低......但是,如果您真的担心并且不需要在应用程序级别进行 ACK,您可以有自己的队列来处理以下情况那。取决于应用程序 - 可能是安装在本地 Web 服务器上的微型 Redis 实例 + python / php 通过 cron / node.js 应用程序在 RabbitMQ 再次可用后推送发送队列?

标签: rabbitmq amqp durability


【解决方案1】:

请阅读here 关于Tx 保证交付

发布者会使用类似的东西:

ch.txSelect();
ch.basicPublish("", QUEUE_NAME,MessageProperties.PERSISTENT_BASIC,"nop".getBytes());
ch.txCommit();

注意:这可能会杀死您的性能应用程序!

编辑

另请阅读@old_sound 建议的“发布者确认”https://www.rabbitmq.com/confirms.html

【讨论】:

  • > 这里的关键词是应该,因为如果代理在有机会将消息写入磁盘之前发生故障,消息仍然可能丢失。
  • 是的,你可以从你的客户端处理它,因为提交失败
  • 您永远不会与任何系统进行 100% 可靠的通信。故事结局。计划故障并建立一个系统来处理最常见和预期的故障。 rabbitmq 会在某个时候下降。您的系统需要知道如何处理它。大多数情况下,这是通过发布方的内存或磁盘缓存消息处理的,等待确认发送以从本地缓存中删除
  • 在 try..catch 中我需要一些代码来“重新发送”消息,否则代理会在崩溃后重启/启动后执行此操作?
  • 它被称为HA client,你必须处理你的消息,然后在服务器启动时重试。 HA client 示例如下:github.com/jhalterman/lyra
【解决方案2】:

查看 Publisher Confirms 以解决知道 RabbitMQ 是否已持久化/复制您的消息的问题:https://www.rabbitmq.com/confirms.html

【讨论】:

    最近更新 更多