RabbitMQ的消息丢失问题

生产环境中可能出现一条消息因为某种原因丢失,为了保证消息不会丢失,需要同时对生产者、消息队列、消费者做出处理.

1.消息在生产者丢失

原因:生产者发送消息成功,但MQ没收到该消息,消息在从生产者传输到MQ的过程中丢失,一般由网络不稳定造成。

解决方案:

RabbitMQ 中提供了 publisher confirm 机制来避免消息发送到 MQ 的过程中丢失的问题。消息发送到 MQ 以后,会返回一个确认结果给生产者,用于表示消息是否确认成功。该确认结果存在两种请求:

  • publisher-confirm

该类型是 发送者确认 ,存在两种情况

  1. 消息成功投递到交换机,返回 ack
  2. 消息未投递到交换机,返回 nack
  • publisher-return

该类型是 发送者回执 ,存在两种情况

  1. 消息投递到交换机,且成功分发到队列,返回 ack
  2. 消息投递到交换机,但未成功分发到队列,返回 nack

发送方采用消息确认机制,当消息成功被MQ接收到后,会给生产者发送一个确认消息,表示接收成功。RabbitMQ发送方确认模式有三种,普通确认、批量确认、异步确认。Spring整合RabbitMQ后只使用了异步监听确认模式

2. 消息在MQ中丢失

原因:消息发送到MQ后,消息还没被消费却在MQ中丢失了。比如MQ服务器宕机或者未进行持久化进行了重启。

解决方案:持久化交换机、队列、消息。MQ 默认是内存存储消息,我们可以通过开启持久化的功能来确保在 MQ 中的消息不丢失,确保MQ服务器重启时仍然能从磁盘恢复对应的交换机,队列和消息。然后我们把MQ做多台分布式集群,防止出现所有的MQ服务器挂掉~

3.消息在消费者丢失

原因:默认消费者消费消息时,设置的是自动恢复MQ收到了消息。MQ会立刻删除自身保存的这条消息,如果消息已经在MQ中被删除,但消费者的业务处理出现异常或消费者服务宕机,那么就会导致该消息没有处理成功从而导致消息丢失。

解决方案:

RabbitMQ 采取的机制是当确认消息被消费者消费后就会立即删除

那么如何确认消息已被消费者消费?那就还得依靠回执来确认,消费者获取消息后,需要向 RabbitMQ 发送 ack 回执,表明自己已经处理消息。其中 ack 在 AMQP 中有三种确认模式:

  • manual:手动 ack,需要在业务代码结束后,调用 api 发送 ack
  • auto:自动 ack,由 spring 监测 listener 代码是否出现异常,没有异常则返回 ack,反之返回 nack
  • none:关闭 ack,MQ 在消息投递后会立即删除消息

消费者向MQ的回复我们设置成手动回复。当消费者出现异常或者服务宕机时,MQ服务器不会删除该消息,而是会把消息重发给绑定该队列的消费者,如果该队列只绑定了一个消费者,则该消息会一直保持在MQ服务器,直到消费者能正常消费为止。具体做法是设置手动ACK

总结:

  • 开启生产者确认机制,确保生产者的消息能到达队列

确认机制包括 publisher-confirm 和 publisher-return

当未送达到 交换机 我们可以通过 publisher-confirm 返回的 ack 和 nack 来确认

当 交换机 未成功路由到 队列,我们可以通过 publisher-return 自定义的回调函数来确认,每个 RabbitTemplate 只能配置一个 ReturnCallback

  • 开启持久化功能,确保消息未消费前在队列中不会丢失

持久化功能分为 交换机持久化队列持久化 和 消息持久化,我们都需要将 durable 设置为 true

  • 开启消费者确认机制最低为 auto 级别

消费者确认机制有三种类型:manual (手动确认)auto (自动确认)none (关闭 ack)

  • 失败重试机制

我们手动设置 MessageResoverer 为 RepublishMessageRecoverer 方式,将投递失败的消息转到异常队列中,交由人工处理

对于 RabbitMQ 消息丢失问题,可以考虑以下几个方面来解决: 1. 持久化消息RabbitMQ 默认情况下将消息存储在内存中,如果 RabbitMQ 服务器重启或崩溃,未持久化的消息丢失。为了解决这个问题,可以将消息标记为持久化,确保消息在重启后能够恢复。在发送消息时,设置 `deliveryMode` 为 2,同时在队列声明时设置 `durable` 为 true。 2. 显式确认模式:使用显式确认模式可以确保消息消费者正确处理后再进行确认,避免消息丢失。在消费者端,可以通过设置 `autoAck` 为 false,然后在处理完消息后手动调用 `basicAck` 方法进行消息确认。 3. 重试机制:当消息消费失败时,可以通过实现重试机制来避免消息丢失。可以在消费者端捕获异常,并将消息重新发送到队列中,设置一定的重试次数或延迟时间,确保消息最终被正确处理。 4. 死信队列(DLX):可以通过配置死信队列,将消费失败的消息发送到一个特定的队列中,然后对该队列进行处理。可以设置死信队列的参数,例如最大重试次数、过期时间等,以便更好地处理消费失败的消息。 5. 监控和日志:及时监控 RabbitMQ 的运行状态和日志,可以帮助发现和解决消息丢失问题。通过监控工具或者自定义脚本,可以实时查看消息队列的状态、消费者的消费情况等,及时发现问题并进行处理。 以上是一些常用的解决 RabbitMQ 消息丢失问题的方法,根据具体的业务场景和需求,可以选择适合的方式进行处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值