RabbitMQ高级
一、简介
RabbitMQ 是一个开源的、基于 Erlang 语言开发的高级消息队列协议(AMQP)的消息代理(Message Broker)和消息中间件。它主要用于在分布式系统中实现应用之间的解耦、异步通信、流量削峰、负载均衡以及提高系统的可扩展性和可靠性。
核心概念:
1.消息代理Broker:接收、存储和转发消息的服务;
2.生产者Producter:消息的发送方,负责创建消息并发送到Broker;
3.消费者Consumer:消息的接收方,连接到Broker并接收、处理消息;
4.队列Queue:存储消息的缓冲区,位于Broker内部。生产者将消息发送到队列,消费者从队列中获取消息;
5.交换机Exchange:生产者并不会将消息直接发送给队列,而是发送给交换机。交换机根据预设的规则(绑定关系和路由键)将消息路由到一个或多个队列;
6.绑定Binding:建立交换机和队列的连接关系;
7.路由键Routing Key:由生产者指定的字符串,用于指定消息应被发送至哪个队列,具体取决于交换机的类型;
8.虚拟主机Virtual Host:逻辑上的隔离单元,类似于命名空间,一个Broker可以包含多个虚拟主机,么个虚拟主机拥有独立的交换机、队列和绑定关系,实现多用户下的资源隔离;
二、消息可靠性
RabbitMQ 的消息可靠性是其核心优势之一,旨在确保消息在传输和处理过程中不丢失。它通过一系列机制来实现高可靠性,主要涵盖消息持久化、发布确认和消费者确认三个方面。
1.消息持久化:这是防止Broker本身故障导致消息丢失的基础手段;
*队列持久化:创建队列时,将其设置为durable(持久化),即使RabbitMQ Broker重启,其队列的原属性也会被保留;但不能保证队列中的消息不丢失;
*交换机持久化:与队列持久化类似,设置为durable(持久化);
*消息持久化:生产者发送消息时,将消息的delively_mode属性设置为2(persistent),这样,MQ会尝试将消息先写入内存,在异步写入磁盘;即使Broker崩溃,消息也能从磁盘中恢复;但即使设置了属性,也不能保证消息不丢失;例如:消息刚写入内存,没有写入磁盘,此时Broker崩溃,消息仍然会丢失;而且持久化会显著降低吞吐量,涉及磁盘I/O;
要达到更高可用性,需要结合发布确认机制。
2.发布确认:确保生产者发送消息成功到达并被Broker正确处理的机制;
原理:
生产者开启Confirm模式后,每发送一条消息,MQ都会在消息被成功处理后向生产者发送一个确认(ACK);如果由于队列已满、内部错误等消息处理失败,MQ也会发送否定确认(NACK)或是直接关闭连接,这样生产者可以重发消息或执行其他补偿逻辑;
3.消费者确认:确保消息被消费者成功处理,防止处理过程中消费者崩溃导致消息丢失的机制;
自动确认(autoAck=true):消息一旦发给消费者后,Broker立刻从队列中删除;如果消费者在处理过程中崩溃,消息将永久丢失;不适用于高可靠性场合;
手动确认(autoAck=true):保证可靠性的标准做法;消费者接收到消息后,必须显式地向Broker发送ACK信号;接收到确认信号后,才会将该消息从队列中删除;
若消费者在处理消息时崩溃,Broker会检测到消费者未确认,会将消息重新入队,并发送给其他消费者或是重启后的原消费者;消费者也可以发送nack否定确认或是reject拒绝,并可以选择是否将消息重新入队。
为了实现端到端的高可用性,通常需要组合使用以上机制;
三、消息重复消费问题
产生的可能原因:
1.消费者处理成功,但未能及时发送确认信号,如:消费者在调用ack确认方法前,出现网络问题,操作系统调度问题,与Broker断开连接;
2.消费者处理过程中崩溃;
3.网络问题;
4.Broker重启,消息未持久化或是持久化未完成,重启后消息会丢失;
5.生产者未收到ack,可能会导致重发消息;
解决方案:
核心思想:保证消息处理的幂等性;即同一条消息无论被消费多少次,其最终的结果都一样,就不会对业务造成影响;
缓存标记:生产者发送消息时,向缓存中写入以ID值和唯一标识的键值对;在消费者消费前,先获取消息的唯一标识,是否在缓存中,若存在,则表示消息未被消费,消费后删除缓存中对应标识;若不存在,则表示该消息已被消费;
四、消息积压问题
产生的原因:
生产者生产消息的速度远高于消费者消费消息的速度,导致消息积压在MQ中;
解决方案:
1.生产者与消费者的从数量上是否能匹配相应的处理速度,如:一个生产者匹配多个消费者;
2.消费者出现异常,需要优化消费者代码;消费者出现宕机,修复宕机情况,临时开启多个消费者,来消耗积压的消息,等到消息不多的情况下,再关闭临时消费者;
3.采用惰性队列,提升消息的存储能力;
4.将消息持久化到本地,之后再读取消费;
五、死信交换机
死信交换机是MQ中的一个高级特性,提供了一些机制来处理无法正常消费的消息;
成为死信交换机的情况:
1.消费者使用basic.reject 或 basic.nack 声明消费失败,并且消息的requeue参数设置为false;
2.消息设置了过期时间,或者消息存放的队列设置了过期时间,超过时间无人消费;
3.投递的队列消息满了,无法投递;
解决方案:
声明DelayExchange交换机:
生产者发送消息:
接收消息,判断消息是否具备x-delay属性,若存在,则说明是延迟消息,持久化到磁盘,读取x-delay的值作为延迟时间;返回routing not found结果给消息发送者;x-delay时间到期后,重新投递消息到指定队列;
六、RadditMQ与Kafka的区别
1.Kafka:
优点:吞吐量大;功能强大:处理流媒体;
缺点:时效性差:消息延迟时间比MQ长
特点:注重Topic,收发消息都必须指定Topic;拉模式:由消费者主动去Broker中拉取消息;消息消费完后,不会删除,保留历史消息;
2.RadditMQ
优点:时效性强、可靠性高;
缺点:吞吐量比Kafka小;
特点:轻Topic,不同工作模式可以选择是否使用Topic;推模式:由Broker主动把消息推送给消费者;消息阅后即焚;