RabbitMQ如何保证消息的可靠性?

从3个层面上考虑,包括生产端,Broker端,消费端。

生产端

使用消息确认机制ack

  • 生产者端在发生消息后可以注册一个回调函数,用于监听消息是否成功送达Broker。
  • 如果消息成功写入队列,RabbMQ会返回一个ack;
  • 如果失败(如队列不存在、交换机不可达),会返回nack。

Broker端

1.持久化

对象 属性 说明
Queue durable=true 队列在服务器重启后仍存在
Exchange durable=true 交换机持久化
Message deliveryMode=2 消息持久化(1=非持久化,2=持久化)

注意:即使设置了持久化,也只能防止 服务器宕机 的消息丢失,不能防止 未被消费就删除 的情况。

2.镜像队列(集群)

  • RabbitMQ集群中使用镜像队列方式,将队列同步到多个节点,这样即使某个节点宕机,其他节点仍可处理该队列的消息,保障高可用。

消费端

1.手动ack

  • 消费者处理完消息后,手动发送basicAck告诉RabbitMQ已经处理完;
  • 如果未确认RabbitMQ不会删除消息;
  • 如果消费程序崩溃,RabbiMQ会将消息重新发送给其他消费者(或者当前重启的消费者)。

2.消息重试与死信队列(DLX)

  • 若消息消费失败,可以通过配置死信队列将其转发,便于后续排查或如果处理
  • 可以结合重试机制避免消息丢失

死信队列

死信队列”是 RabbitMQ 中的一种机制,用于处理无法被正常消费的消息,可以防止消息丢失并实现异常追踪、告警处理、消息重发、补偿机制。

  1. 消息被拒绝(rejected),并且 requeue=false
  2. 消息过期(TTL 到期)
  3. 队列已满,无法继续投递消息

那如何保证消息不重复消费呢?