RabbitMQ通过一系列机制来避免消息的重复投递和重复消费,确保消息的可靠传输和处理。
1.消息去重:
-
在发送端去重:在发送消息之前,可以在消息的唯一标识字段上进行去重操作。使用数据库或缓存来记录已经发送的消息的标识,每次发送消息之前先查询是否已存在相同标识的消息,如果存在则不发送。这样可以避免消息的重复发送。
-
使用去重插件:RabbitMQ提供了一些去重插件,如rabbitmq-deduplication插件。这些插件可以在消息发送时自动进行去重操作,根据消息的内容生成唯一的消息ID,并在发送之前检查是否已存在相同ID的消息,从而避免重复发送。
2.消息确认机制:
-
消费者确认:消费者在处理完消息后,可以发送确认消息给RabbitMQ,告知消息已经被正确处理。RabbitMQ收到确认消息后,会将该消息从队列中删除,避免消息的重复消费。
-
confirm(发布确认)机制:RabbitMQ支持开启confirm模式,生产者每次发送消息都会分配一个唯一的ID。当RabbitMQ成功接收到消息后,会异步回调生产者的接口返回成功与否的消息。如果消息处理失败,RabbitMQ会回调生产者的nack接口,通知消息接收失败,生产者可以重新发送。这样结合内存维护消息ID状态,可以重发丢失的消息。
3.使用全局唯一标识:
-
消息全局ID或唯一标识:每次消费消息之前,根据消息ID去判断该消息是否已消费过。如果已经消费过,则不处理这条消息;否则正常消费,并进行入库操作。
-
利用Redis的setnx命令:给消息分配一个全局ID,消费消息时,先去Redis中查询是否有消费记录。如果没有,则以键值对形式写入Redis;如果有,则不消费该消息。
-
持久化:
-
开启RabbitMQ的持久化:确保队列和消息都被持久化到磁盘上,以防止在RabbitMQ重启或故障时丢失消息。
-
合理设计消费者逻辑:
-
确保消费者在处理消息时具有幂等性
-
多次执行相同的操作不会产生不同的结果,以避免重复消费导致的副作用。