RMQ 消息确认机制
RabbitMQ 通过消息确认机制来保障消息从队列到消费者的可靠传递,该机制主要分为两种:
自动确认(Auto Acknowledge,autoACK):
在这种模式下,RabbitMQ 在将消息推送到消费者后立即将消息标记为已确认。这意味着不管消费者是否成功处理了该消息,消息都会被从队列中删除。
这种模式可以提高吞吐量,但存在消息丢失的风险,因为如果消费者在处理消息时失败,消息已经被删除。手动确认(Manual Acknowledge):
在这种模式下,消费者在成功处理消息后,显式地向 RabbitMQ 发送确认(ACK)信号。
如果消费者没有发送 ACK 信号,消息会一直留在队列中,直到被明确确认或者重新投递(根据配置)。
为了保证消息的可靠性,一般优先推荐使用手动确认模式。
问:队列如何知道某个消费者已经空闲,并且可以接受新的消息?
答:1. 在手动确认模式下,队列正是通过消费者的 ACK 信号来判断该消费者是否处于空闲状态,从而决定是否可以推送新的消息给该消费者。2. 而在自动确认模式下,由于不存在 ACK 信号。所以队列不知道也不在乎消费者是否处于空闲,有消息就会推。这也是为什么虽然自动确认模式可以提高吞吐量,但我们通常更建议使用手动确认模式。
Spring AMQP 消息确认模式 vs RMQ 消息确认模式
当我们在 Spring 框架下基于 Spring AMQP 使用 RMQ 时需要注意,Spring AMQP 框架定义的消息确认模式(参考:org.springframework.amqp.core.AcknowledgeMode
枚举类)和RMQ官网定义的消息确认模式并不完全是一回事,需要区分看待。
Spring AMQP 的消息确认模式总共有三种:
-
NONE
- 对应 RMQ 的 Auto Ack,即消费者无需 ack; -
MANUAL
- 对应 RMQ 的 Manual Ack,需要开发者在代码中明确发起 ack;
以使用@RabbitListener
为例,如果采用手动确认模式,即@RabbitListener
注解参数ackMode = "MANUAL"
,那么开发者需要在@RabbitListener
注解的方法内明确调用 ack; -
AUTO
- 对应 RMQ 的 Manual Ack,Spring 框架会自动帮你调用 ack;
以使用@RabbitListener
为例,AUTO
是@RabbitListener
默认采用的确认模式,框架会在@RabbitListener
注解的方法正常返回时,自动调用ack
,抛异常时自动调用nack
。
当你使用 Spring AMQP 的 basicConsume 方法传入 autoAck = true 时,对应的 Spring AMQP 确认模式是 NONE。