一.RabbitMQ如何避免消息重复投递或重复消费?
RabbitMQ通过一系列机制来避免消息的重复投递和重复消费,确保消息的可靠传输和处理。
- 消息去重:
-
- 在发送端去重:在发送消息之前,可以在消息的唯一标识字段上进行去重操作。使用数据库或缓存来记录已经发送的消息的标识,每次发送消息之前先查询是否已存在相同标识的消息,如果存在则不发送。这样可以避免消息的重复发送。
- 使用去重插件:RabbitMQ提供了一些去重插件,如rabbitmq-deduplication插件。这些插件可以在消息发送时自动进行去重操作,根据消息的内容生成唯一的消息ID,并在发送之前检查是否已存在相同ID的消息,从而避免重复发送。
- 消息确认机制:
-
- 消费者确认:消费者在处理完消息后,可以发送确认消息给RabbitMQ,告知消息已经被正确处理。RabbitMQ收到确认消息后,会将该消息从队列中删除,避免消息的重复消费。
- confirm(发布确认)机制:RabbitMQ支持开启confirm模式,生产者每次发送消息都会分配一个唯一的ID。当RabbitMQ成功接收到消息后,会异步回调生产者的接口返回成功与否的消息。如果消息处理失败,RabbitMQ会回调生产者的nack接口,通知消息接收失败,生产者可以重新发送。这样结合内存维护消息ID状态,可以重发丢失的消息。
- 使用全局唯一标识:
-
- 消息全局ID或唯一标识:每次消费消息之前,根据消息ID去判断该消息是否已消费过。如果已经消费过,则不处理这条消息;否则正常消费,并进行入库操作。
- 利用Redis的setnx命令:给消息分配一个全局ID,消费消息时,先去Redis中查询是否有消费记录。如果没有,则以键值对形式写入Redis;如果有,则不消费该消息。
- 持久化:
-
- 开启RabbitMQ的持久化:确保队列和消息都被持久化到磁盘上,以防止在RabbitMQ重启或故障时丢失消息。
- 合理设计消费者逻辑:
-
- 确保消费者在处理消息时具有幂等性,即多次执行相同的操作不会产生不同的结果,以避免重复消费导致的副作用。
二.RabbitMQ消息基于什么传输?
RabbitMQ消息主要基于高级消息队列协议(AMQP)进行传输。AMQP是一种开放、可靠、面向消息的中间件协议,它允许应用程序通过消息代理(如RabbitMQ)进行通信。RabbitMQ实现了AMQP协议,为应用程序提供了一种灵活且可靠的消息传递机制。
在RabbitMQ中,消息被发送到队列中,并且按照特定的规则进行消费。生产者连接到RabbitMQ服务器并创建一个通道,然后声明一个队列并将消息发送到该队列中。消费者也连接到RabbitMQ服务器并创建一个通道,从队列中获取消息并进行处理。当消息被消费者处理完毕后,会发送一个确认消息给RabbitMQ服务器,服务器随后删除已确认的消息。
此外,RabbitMQ还支持多种交换机类型来实现不同的路由机制,如直接交换机、主题交换机和扇形交换机等,这些交换机决定了消息如何被路由到不同的队列中。同时,RabbitMQ还提供了消息的持久化、消费者的负载均衡等特性,以确保消息的可靠传输和处理。
三.RabbitMQ消息如何分发?
RabbitMQ的消息分发机制是其核心功能之一,它允许生产者发送消息到队列,并由消费者从队列中获取并处理这些消息。
- 简单模式:这是最基本的工作模式。一个生产者将消息发送到一个队列中,一个消费者从队列中获取并处理消息。这种模式适用于简单的、一对一的消息传递场景。
- 工作队列模式:这种模式用于实现一个任务在多个消费者之间的并发处理。一个生产者将消息发送到一个队列中,多个消费者从队列中获取并处理消息。每个消息只能被一个消费者处理,这确保了任务的唯一性。
- 发布/订阅模式:在这种模式下,一个生产者将消息发送到交换器中,交换器将消息广播到所有绑定的队列,每个队列对应一个消费者。这允许消息被多个消费者同时处理,适用于需要广播消息的场景。
- 路由模式:此模式用于实现根据消息的路由键(Routing key)将消息路由到不同的队列中。生产者发送消息时指定路由键,RabbitMQ根据路由键和队列的绑定关系将消息发送到相应的队列。
- 主题模式:这是一种更灵活的消息路由模式。它使用通配符匹配路由键,将消息路由到多个队列中。生产者发送消息时指定主题作为路由键,交换器根据通配符匹配将消息路由到匹配的队列中。
除了上述基本模式外,RabbitMQ还提供了其他一些分发策略和优化机制,如:
- 轮询分发:消息队列会按照一定的机制将消息推送给消费者,这种规则是一种公平的分发,不会因为消费者的延时而造成不公平性。一旦有一个消费者消费了消息,后面的消费者就不会重复的去消费消息。
- 公平分发:这种分发方式会按照服务器的性能来分配消息,快的消费者处理更多的消息,慢的处理较少的消息。这可能会造成数据的倾斜,但确保了能者多劳。
- 预值分发:当消息被消费者接收后但没有确认时,会存在一个未确认的消息缓冲区。预取值定义了通道上允许的未确认消息的最大数量,这有助于管理内存消耗和确保最佳的吞吐量。
四.RabbitMQ消息怎么路由?
RabbitMQ中的消息路由是通过交换机(Exchange)来实现的。交换机接收生产者发送的消息,然后根据预定义的规则将消息路由到一个或多个消息队列中。RabbitMQ支持多种类型的交换机,每种类型都有其特定的路由规则。
- 直连交换机(Direct Exchange):这是最简单和最常用的交换机类型。它将消息路由到与消息的路由键(Routing Key)完全匹配的队列。每个队列通过绑定键(Binding Key)与交换机进行绑定,当消息发送到交换机时,交换机会检查消息的路由键,并将其路由到绑定键与之完全匹配的队列中。
- 主题交换机(Topic Exchange):它根据消息的路由键与绑定键之间的模式匹配规则来路由消息。与直连交换机不同,主题交换机支持通配符匹配,这使得它可以实现更复杂的路由逻辑。
- 扇形交换机(Fanout Exchange):它将消息广播到所有绑定到该交换机上的队列中,不考虑消息的路由键。这种类型的交换机适用于需要将消息发送到多个消费者进行处理的场景。
- 头交换机(Headers Exchange):它根据消息的头部属性进行匹配,将消息路由到与之匹配的队列中。这种类型的交换机提供了更灵活的匹配规则,但相对于其他类型的交换机,其使用场景较为特殊。
在配置消息路由时,生产者需要将消息发送到特定的交换机,并指定一个路由键。交换机根据路由键和队列的绑定关系,将消息路由到相应的队列中。消费者则从队列中获取并处理消息。
通过合理地配置交换机、队列和绑定关系,RabbitMQ可以实现灵活且可靠的消息路由,满足各种复杂的业务需求。