RabbitMQ入门指南(八):MQ可靠性

简介: RabbitMQ是一个高效、可靠的开源消息队列系统,广泛用于软件开发、数据传输、微服务等领域。本文主要介绍了MQ数据持久化、LazyQueue模式、管理控制台配置Lazy模式、代码配置Lazy模式、更新已有队列为lazy模式等内容。

一、MQ数据持久化

在消息队列(MQ)中,数据的持久化至关重要。如果MQ不能及时保存消息,可能会导致数据丢失。为了确保数据的可靠性,必须配置数据持久化。

1.交换机持久化

在RabbitMQ管理控制台新建交换机时可以配置交换机的Durability参数:

  • Durable:持久化模式
  • Transient:临时模式


代码声明交换机时,默认为持久化模式,DirectExchange源码:

public DirectExchange(String name) {
        super(name);
    }
    public DirectExchange(String name, boolean durable, boolean autoDelete) {
        super(name, durable, autoDelete);
    }
    public DirectExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments) {
        super(name, durable, autoDelete, arguments);
    }

image.gif

AbstractExchange源码(DirectExchange extends AbstractExchange):

public AbstractExchange(String name) {
        this(name, true, false);
    }
    public AbstractExchange(String name, boolean durable, boolean autoDelete) {
        this(name, durable, autoDelete, (Map)null);
    }
    public AbstractExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments) {
        super(arguments);
        this.name = name;
        this.durable = durable;
        this.autoDelete = autoDelete;
    }

image.gif

2.队列持久化

在RabbitMQ管理控制台新建队列时可以配置队列的Durability参数:

  • Durable:持久化模式
  • Transient:临时模式


代码声明队列时,默认为持久化模式,源码如下:

public Queue(String name) {
        this(name, true, false, false);
    }
    public Queue(String name, boolean durable) {
        this(name, durable, false, false, (Map)null);
    }
    public Queue(String name, boolean durable, boolean exclusive, boolean autoDelete) {
        this(name, durable, exclusive, autoDelete, (Map)null);
    }
    public Queue(String name, boolean durable, boolean exclusive, boolean autoDelete, @Nullable Map<String, Object> arguments) {
        super(arguments);
        Assert.notNull(name, "'name' cannot be null");
        this.name = name;
        this.actualName = StringUtils.hasText(name) ? name : Base64UrlNamingStrategy.DEFAULT.generateName() + "_awaiting_declaration";
        this.durable = durable;
        this.exclusive = exclusive;
        this.autoDelete = autoDelete;
    }

image.gif

3.消息持久化

在控制台发送消息的时候,可以通过配置消息的属性来实现消息的持久化。消息持久化是将消息保存在磁盘上,即使MQ重启,消息也不会丢失。在发送消息时,可以选择Delivery mode参数来配置消息的持久化属性。


查看消息:


4.生产者确认机制

在开启持久化机制以后,如果同时还开启了生产者确认,那么MQ会在消息持久化以后才发送ACK回执给生产者,进一步确保消息的可靠性。为了减少IO次数并提高性能,MQ并不会逐条将消息持久化到数据库,而是每隔一段时间批量进行持久化。因此,建议生产者确认全部采用异步方式,以避免ACK的延迟。

二、LazyQueue

1.LazyQueue模式介绍

在 RabbitMQ 的默认设置中,为了降低消息收发的延迟,它会将接收到的信息保存在内存中。然而,在某些特殊情况下,这种设置可能会导致消息积压。以下是几种可能导致消息积压的情况:

  • 消费者宕机或出现网络故障:当消费者无法正常处理消息时,RabbitMQ 将无法将消息传递给消费者,从而导致消息积压。
  • 消息发送量激增,超过了消费者处理速度:当消息发送速度超过消费者的处理速度时,消息将在 RabbitMQ 的队列中积压。
  • 消费者处理业务发生阻塞:如果消费者在处理消息时遇到业务阻塞,例如等待某些资源或进行耗时的操作,那么它可能会花费更长的时间来处理消息,从而导致消息积压。

当消息堆积问题出现时,RabbitMQ 的内存占用会逐渐增加,直到触发内存预警上限。此时,RabbitMQ 将开始将内存中的消息刷写到磁盘上,这个过程称为“PageOut”。“PageOut”过程会耗费一定的时间,并且会阻塞队列进程。因此,在这个过程中,RabbitMQ 将无法处理新的消息,导致生产者的所有请求都被阻塞。

为了解决这个问题,从 RabbitMQ 3.6.0 版本开始,引入了 Lazy Queues(惰性队列)模式。惰性队列具有以下特征:

  • 接收到消息后直接存入磁盘而非内存:在惰性队列中,消息在接收到后不会立即加载到内存中,而是直接存储在磁盘上。
  • 消费者要消费消息时才会从磁盘中读取并加载到内存(也就是懒加载):当消费者需要消费消息时,它才会从磁盘中读取消息并加载到内存中。这样可以避免在消费者不活跃时浪费内存资源。
  • 支持数百万条的消息存储:惰性队列支持大量的消息存储,即使在没有内存限制的情况下也能处理大量的消息。

在RabbitMQ 3.12 版本之后,LazyQueue 已经成为所有队列的默认格式。这种模式可以有效地解决消息积压问题,提高 RabbitMQ 的性能和稳定性。

2.管理控制台配置Lazy模式

在新建队列的时候,添加x-queue-mode=lazy参数设置队列为Lazy模式(RabbitMQ 3.12 版本之前):


3.代码配置Lazy模式

在使用Spring AMQP声明队列的时候,添加x-queue-mod=lazy参数设置队列为Lazy模式:

@Bean
    public Queue lazyQueue() {
        // .lazy()开启Lazy模式
        return QueueBuilder.durable("lazy.queue").lazy().build();
    }

image.gif

源码如下:

public QueueBuilder lazy() {
        return this.withArgument("x-queue-mode", "lazy");
    }

image.gif

基于注解来声明队列并设置为Lazy模式:

@RabbitListener(queuesToDeclare = @Queue(
            name = "lazy.queue",
            durable = "true",
            arguments = @Argument(name = "x-queue-mode", value = "lazy")))
    public void listenLazyQueue(String msg){
        log.info("lazy.queue:{}", msg);
    }

image.gif

4.更新已有队列为lazy模式

基于命令行设置policy实现将已有队列更新为lazy模式:

rabbitmqctl set_policy Lazy "^lazy-queue$" '{"queue-mode":"lazy"}' --apply-to queues

image.gif

rabbitmqctl RabbitMQ的命令行工具
set_policy 添加一个策略
Lazy 策略名称
"^lazy-queue$" 用正则表达式匹配队列的名字
'{"queue-mode":"lazy"}' 设置队列模式为lazy模式
--apply-to queues 策略的作用对象,是所有的队列

管理控制台配置policy(RabbitMQ 3.12 版本之前):



总结

RabbitMQ是一个开源的消息队列软件,旨在提供可靠的消息传递和消息队列功能。本文主要介绍了MQ数据持久化、LazyQueue模式、管理控制台配置Lazy模式、代码配置Lazy模式、更新已有队列为lazy模式等内容,希望对大家有所帮助。

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
4月前
|
消息中间件 Java Kafka
消息传递新纪元:探索RabbitMQ、RocketMQ和Kafka的魅力所在
【8月更文挑战第29天】这段内容介绍了在分布式系统中起到异步通信与解耦作用的消息队列,并详细探讨了三种流行的消息队列产品:RabbitMQ、RocketMQ 和 Kafka。其中,RabbitMQ 是一个基于 AMQP 协议的开源消息队列系统,支持多种消息模型;RocketMQ 则是由阿里巴巴开源的具备高性能、高可用性和高可靠性的分布式消息队列,支持事务消息等多种特性;而 Kafka 作为一个由 LinkedIn 开源的分布式流处理平台,以高吞吐量和良好的可扩展性著称。此外,还提供了使用这三种消息队列发送和接收消息的代码示例。总之,这三种消息队列各有优势,适用于不同的业务场景。
75 3
|
1月前
|
消息中间件 大数据 Kafka
大厂面试高频:Kafka、RocketMQ、RabbitMQ 的优劣势比较
本文深入探讨了消息队列的核心概念、应用场景及Kafka、RocketMQ、RabbitMQ的优劣势比较,大厂面试高频,必知必会,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:Kafka、RocketMQ、RabbitMQ 的优劣势比较
|
2天前
|
消息中间件 Java 中间件
MQ四兄弟:如何保证消息可靠性
本文介绍了RabbitMQ、RocketMQ、Kafka和Pulsar四种消息中间件的可靠性机制。这些中间件通过以下几种方式确保消息的可靠传输:1. 消息持久化,确保消息在重启后不会丢失;2. 确认机制,保证消息从生产者到消费者都被成功处理;3. 重试机制,处理失败后的重试;4. 死信队列,处理无法消费的消息。每种中间件的具体实现略有不同,但核心思想相似,都是从生产者、中间件本身和消费者三个角度来保障消息的可靠性。
12 0
|
1月前
|
消息中间件 存储 监控
ActiveMQ、RocketMQ、RabbitMQ、Kafka 的区别
【10月更文挑战第24天】ActiveMQ、RocketMQ、RabbitMQ 和 Kafka 都有各自的特点和优势,在不同的应用场景中发挥着重要作用。在选择消息队列时,需要根据具体的需求、性能要求、扩展性要求等因素进行综合考虑,选择最适合的消息队列技术。同时,随着技术的不断发展和演进,这些消息队列也在不断地更新和完善,以适应不断变化的应用需求。
103 1
|
2月前
|
消息中间件 数据采集 数据库
小说爬虫-03 爬取章节的详细内容并保存 将章节URL推送至RabbitMQ Scrapy消费MQ 对数据进行爬取后写入SQLite
小说爬虫-03 爬取章节的详细内容并保存 将章节URL推送至RabbitMQ Scrapy消费MQ 对数据进行爬取后写入SQLite
34 1
|
2月前
|
消息中间件 Java Kafka
RabbitMQ 入门
RabbitMQ 入门
|
3月前
|
消息中间件 监控 物联网
MQTT协议对接及RabbitMQ的使用记录
通过合理对接MQTT协议并利用RabbitMQ的强大功能,可以构建一个高效、可靠的消息通信系统。无论是物联网设备间的通信还是微服务架构下的服务间消息传递,MQTT和RabbitMQ的组合都提供了一个强有力的解决方案。在实际应用中,应根据具体需求和环境进行适当的配置和优化,以发挥出这两个技术的最大效能。
206 0
|
4月前
|
消息中间件 存储 Java
分享一下rocketmq入门小知识
分享一下rocketmq入门小知识
57 0
分享一下rocketmq入门小知识
|
4月前
|
消息中间件 存储 运维
RabbitMQ-消息消费时的可靠性保障
将这些实践融入到消息消费的处理逻辑中,可以很大程度上保障RabbitMQ中消息消费的可靠性,确保消息系统的稳定性和数据的一致性。这些措施的实施,需要在系统的设计和开发阶段充分考虑,以及在后续的维护过程中不断的调整和完善。
64 0
|
2月前
|
消息中间件 JSON Java
开发者如何使用轻量消息队列MNS
【10月更文挑战第19天】开发者如何使用轻量消息队列MNS
97 5
下一篇
DataWorks