RabbitMQ的ack机制
1、什么是消息确认ACK。
答:如果在处理消息的过程中,消费者的服务器在处理消息的时候出现异常,那么可能这条正在处理的消息就没有完成消息消费,数据就会丢失。为了确保数据不会丢失,RabbitMQ支持消息确定-ACK。
2、RabbitMQ的ACK的消息确认机制。
1、ACK机制是消费者从RabbitMQ收到消息并处理完成后,反馈给RabbitMQ,MQ收到反馈后才将此消息从队列中删除。消息的ACK确认机制默认是打开的。
2、如果一个消费者在处理消息出现了网络不稳、服务器异常等现象,那么就不会有ACK反馈,RabbitMQ会认为这个消息没有正常消费,会将消息重新放入队列。
3、如果在集群的情况下,RabbitMQ会立即将这个消息推送给这个在线的其他消费者。这种机制保证了在消费者服务端故障的时候,不丢失任何消息和任务。
4、消息永远不会从RabbitMQ中删除,只有当消费者正确发送ACK反馈,RabbitMQ确认收到后,消息才会从RabbitMQ服务器的数据中删除。
3、ACK机制的开发注意事项?
如果消费者发生异常,ack没法送消息应答。,Message会一直重新分发。然后RabbitMQ会占用越来越多的内容,由于RabbitMQ会长时间运行,因此这个"内存泄漏"是致命的。
4.怎么解决ack的内存泄漏问题?
1、在程序处理中可以进行异常捕获,保证消费者的程序正常执行。
2、使用RabbitMQ的ack的配置确认机制。(开启重试次数)
3、手动设置消息应答。如果消费端异常,也返回应答成功,再把未消费成功的数据记录下来,进行补偿。
# 开启重试 32 spring.rabbitmq.listener.simple.retry.enabled=true 33 # 重试次数,默认为3次 34 spring.rabbitmq.listener.simple.retry.max-attempts=5
//第二个参数值为false代表关闭RabbitMQ的自动应答机制,改为手动应答。 channel.basicConsume(QUEUE_NAME, false, consumer); //在处理完消息时,返回应答状态。 channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
5、消费端的手工ACK与NACK?
2、当我们手工 ACK 时,会发送给Broker一个应答,代表消息成功处理了,Broker就可以回送响应给生产端了。NACK 则表示消息处理失败了,如果设置重回队列,Broker端就会将没有成功处理的消息重新发送。
使用方法:void basicNack(long deliveryTag, boolean multiple, boolean requeue):
1、参数:requeue为true,表示deliveryTag=n之前未确认的消息都处理失败且将这些消息重新放回队列中。
2、参数:requeue为false,表示deliveryTag=n之前未确认的消息都处理失败且将这些消息直接丢弃。
3、如果由于服务器宕机等严重问题,那我们就需要手工进行 ACK 保障消费端消费成功!方法:void basicAck(long deliveryTag, boolean multiple)