Rabbitmq
RabbitMQ是一个开源的、实现了高级消息队列协议(AMQP, Advanced Message Queuing Protocol)的消息中间件(Message Broker)。它使用Erlang语言开发,这门语言以其在构建高并发、高可靠性、分布式系统方面的优势而闻名,因此RabbitMQ天生就具备了很好的稳定性和性能。
简单来说,RabbitMQ就像一个现实生活中的邮局。生产者(Producer)将消息(信件)发送到邮局,邮局(RabbitMQ)根据规则(路由规则)将信件投递到不同的邮箱(队列),最终由消费者(Consumer)从邮箱中取出并处理信件。它的核心作用是应用解耦、异步处理和流量削峰。
核心组件
-
Producer (生产者):发送消息的应用程序。
-
Consumer (消费者):接收并处理消息的应用程序。
-
Broker: 指的是RabbitMQ服务本身,它接收来自生产者的消息,并将其路由给消费者。
-
Queue (队列):位于RabbitMQ内部,用于存储消息的缓冲区,类似于邮箱。消息最终被投递到这里,等待消费者来获取。队列可以有多个消费者,消息会以轮询(Round-robin)的方式分发给它们。
-
Exchange (交换机):这是RabbitMQ中非常重要的一个概念,它接收来自生产者的消息,并根据特定的规则将消息路由到一个或多个队列中。交换机本身不存储消息,它只是一个路由中转站。
-
Binding (绑定):定义了Exchange和Queue之间的关联关系。一个绑定就是一条规则,它告诉交换机如何将消息路由到指定的队列。绑定通常会附带一个Routing Key。
标准工作流程如下:
-
生产者将消息发送给一个指定的Exchange。发送时,通常会附带一个Routing Key。
-
Exchange收到消息后,会查找所有与自己绑定的Queue。
-
根据Exchange的类型和消息的Routing Key,与每个Queue绑定的Binding Key进行匹配。
-
如果匹配成功,Exchange就会将消息的一份拷贝放入对应的Queue中。
-
消费者监听某个Queue,当Queue中有消息时,就会接收并进行处理。
Exchange的四种主要类型:
-
Direct Exchange (直连交换机):它会把消息路由到那些Binding Key与Routing Key完全匹配的队列中。这是最简单直接的匹配方式。
-
Fanout Exchange (扇形交换机):它会忽略Routing Key,将接收到的所有消息广播到所有与其绑定的队列中。非常适合做“发布/订阅”模式,比如系统通知广播。
-
Topic Exchange (主题交换机):这是最灵活的一种。它支持使用通配符来匹配Routing Key和Binding Key。
*(星号)可以替代一个单词,#(井号)可以替代零个或多个单词。例如,一个Routing Key为log.error.database的消息,可以被log.error.*或log.#的Binding Key匹配到。 -
Headers Exchange (头交换机):不依赖于Routing Key进行匹配,而是根据消息头(Headers)中的键值对来进行匹配。性能上相对较差,使用场景不多。
可靠性保障
RabbitMQ不仅仅是简单地传递消息,它还提供了一系列机制来保证消息处理的可靠性。
-
消息持久化:为了防止RabbitMQ服务器宕机导致消息丢失,我们可以将Exchange、Queue和消息本身都设置为持久化(Durable)。这样,即使服务重启,相关的配置和消息也能恢复。
-
消费确认机制 (Acknowledgements, ack):默认情况下,当RabbitMQ将消息推送给消费者后,会立即在队列中删除该消息。但如果此时消费者进程异常退出,消息就会丢失。为了解决这个问题,可以开启手动ack模式。消费者在成功处理完消息后,会向RabbitMQ发送一个ack回执,此时RabbitMQ才会真正删除消息。如果消费者在处理过程中断开连接(或发送nack),RabbitMQ会认为消息没有被成功处理,并将其重新投递给其他消费者。
-
生产者确认机制 (Publisher Confirms):为了保证消息从生产者可靠地到达RabbitMQ服务器,可以开启Publisher Confirms模式。开启后,生产者发送的每条消息都会被分配一个唯一ID,当消息被RabbitMQ成功接收后,RabbitMQ会回调生产者的一个接口,告知消息已成功送达。如果消息在网络中丢失或RabbitMQ内部出错,生产者就无法收到确认,从而可以进行重发。
-
高可用性:
-
集群 (Clustering):可以将多个RabbitMQ节点组成一个集群,所有节点共享元数据(队列、交换机、用户等信息)。客户端可以连接到集群中的任意节点。但这并不能保证队列中消息的高可用,因为默认情况下,队列及其内容只存在于创建它的那个节点上。
-
镜像队列 (Mirrored Queues):为了解决单点故障问题,可以在集群的基础上配置镜像队列。一个镜像队列会有一个主节点(Master)和若干个从节点(Slave)。所有发送到主节点的消息都会被自动复制到所有从节点。当主节点宕机后,最老的从节点会自动提升为新的主节点,从而保证服务的连续性和消息的可用性。
-