首页 > 其他分享 >RabbitMQ高级篇之MQ可靠性 Lazy Queue

RabbitMQ高级篇之MQ可靠性 Lazy Queue

时间:2025-01-08 12:32:29浏览次数:11  
标签:Lazy 队列 写入 RabbitMQ Queue 惰性 磁盘 内存

文章目录

数据持久化的背景和挑战

持久化确保了即使 RabbitMQ 崩溃或重启,消息仍然不会丢失。同时,消息不会因为内存溢出而触发 paged out 操作,从而避免了性能下降。

但是,持久化也带来了一个问题:每条消息必须保存到内存和磁盘中,这导致了写入操作的延迟,从而降低了系统的整体并发能力。



引入惰性队列(Lazy Queue)

为了弥补这一性能损失,RabbitMQ 从 3.6 版本 引入了 惰性队列(Lazy Queue) 模式。惰性队列的目标是:

  • 提升并发能力,同时确保消息不会丢失。
  • 减少内存占用,避免内存满导致的阻塞。



惰性队列的特点

惰性队列有两个显著特点:

  1. 直接将消息写入磁盘,而不是先写入内存
    • 传统队列会首先将消息保存到内存中,然后根据是否需要持久化决定是否将其写入磁盘。
    • 惰性队列则直接将消息写入磁盘,而不经过内存。这减少了内存压力和避免了因内存满导致的系统阻塞(如 page out)。
  2. 磁盘写入优化
    • 惰性队列通过优化磁盘写入操作,提高了写入效率,比传统的持久化方式要高效得多。



惰性队列的潜在问题

尽管惰性队列解决了内存占用和阻塞问题,但也引入了新的挑战:

  • 消费者读取延迟:消息被直接写入磁盘,消费者在读取时需要将消息从磁盘加载到内存,再投递给消费者。如果消费者的处理速度很快,但磁盘读取速度较慢,可能会影响消费者的处理速度。

为了解决这一问题,RabbitMQ 进行了进一步优化:

  • 动态缓存机制:RabbitMQ 会根据消费者的处理速度动态调整消息的加载方式。
    • 如果消费者处理消息的速度较慢,RabbitMQ 直接从磁盘加载消息。
    • 如果消费者处理消息的速度较快,RabbitMQ 会提前将部分消息加载到内存中(最多 2048 条),避免磁盘读取的瓶颈影响消费者的处理速度。



RabbitMQ 中的惰性队列实现

  • RabbitMQ 3.12 版本 开始,所有队列默认都采用惰性队列模式,无法更改为传统队列模式。
  • 3.8 版本 及以下的 RabbitMQ 中,若要使用惰性队列,需要手动配置。

如何创建惰性队列(Lazy Queue)

在 RabbitMQ 中,可以通过控制台、代码或注解来创建惰性队列。

在控制台中创建惰性队列:

  1. 创建一个队列时,勾选 Lazy Mode,系统会自动将参数 x-queue-mode=lazy 加入队列的 arguments 中。



通过代码创建惰性队列:

  • 使用 QueueBuilder 来声明队列时,调用 lazy() 方法来启用惰性队列模式。例如:

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

通过注解创建惰性队列:

  • 使用 @Queue 注解时,添加 arguments 参数来设置 x-queue-mode=lazy,从而声明惰性队列。例如:

@RabbitListener(queuesToDeclare = @Queue(
    name = "lazy.queue",
    dueable = "true",
    arguments = @Argument(name = "x-queue-mode", value = "lazy")
))
public void listenLazyQueue(String msg) {
    log.info("接收到 lazy.queue 的消息:{}", msg);
}

惰性队列的性能测试

  • 在实际测试中,通过发送 100 万条消息 到惰性队列,可以看到处理的速度非常快,每秒处理 4 万到 5 万条消息,而且处理时间保持稳定,性能高于传统持久化队列。
  • 相比传统队列,惰性队列避免了消息在内存中的存储,减少了内存压力,避免了内存满导致的 paged out 和阻塞问题。



惰性队列的优势

  • 保证消息不丢失:即使 RabbitMQ 崩溃或重启,惰性队列依然能保证消息的持久性。
  • 提升并发能力:由于不再需要将消息先存储到内存,写入磁盘的效率得到提升,从而增强了队列的处理能力。
  • 避免内存阻塞:不会出现因为内存满导致的消息阻塞和系统停顿。



惰性队列的适用场景

  • 适合高吞吐量且对延迟要求不高的场景。惰性队列通过减少内存的使用,并且优化磁盘写入,显著提升了消息队列的并发能力和稳定性,适用于大量消息处理的系统。
  • 对于一些高并发的应用场景,使用惰性队列能够更好地处理负载,提高系统的响应能力。

小结

  • 惰性队列(Lazy Queue)是 RabbitMQ 中为了解决持久化队列带来的性能问题而引入的新队列模式。
  • 通过直接将消息写入磁盘、避免写入内存和内存溢出,惰性队列不仅保证了消息不丢失,还提升了并发处理能力。
  • 在使用 RabbitMQ 时,如果对消息吞吐量和并发能力有较高要求,建议使用惰性队列模式。

关键点总结

  1. 惰性队列(Lazy Queue):直接将消息写入磁盘,避免内存占用,提高并发能力。
  2. 磁盘写入优化:相比传统持久化队列,惰性队列在写磁盘时更加高效,减少了 page out 阻塞问题。
  3. 消费者动态缓存:根据消费者处理速度调整内存缓存,优化读取性能。
  4. 使用方式
    • 控制台:勾选 Lazy Mode
    • 代码:使用 lazy() 方法。
    • 注解:通过 arguments 配置 x-queue-mode=lazy

标签:Lazy,队列,写入,RabbitMQ,Queue,惰性,磁盘,内存
From: https://blog.csdn.net/2301_80093566/article/details/144828399

相关文章

  • RabbitMQ高级篇之消费者可靠性 业务幂等处理
    文章目录消息消费中的可靠性问题业务幂等性消息重复消费的原因如何确保业务幂等性解决方案方案一:唯一消息ID方案二:业务逻辑判断异常处理与重试机制消息的持久化与可靠性面试问题回顾总结代码示例配置消息ID生成消费者接收消息时获取消息ID订单支付状态判断消息消......
  • RabbitMQ高级篇之延迟消息 介绍
    文章目录延迟消息的概念支付与交易服务一致性问题解决方案:延迟消息支付订单流程延迟消息的实现延迟消息的业务场景总结关键技术点业务流程总结实践建议延迟消息的概念延迟消息是指发送者在发送消息时,指定一个时间,消费者在指定时间后才能接收到消息,而不是立即接收。......
  • Windows10环境下安装RabbitMq折腾记
            最近有个老项目需要迁移到windows10环境,用的是比较老的rabbitmq安装包,如下所示。经过一番折腾,死活服务起不来,最终果断放弃老版本启用新版本。现在把折腾过程记录下:一、安装erlang 安装完成后的目录结构,我的路径是D:\Apps\EnvSoft\ErlangOPT21。:    ......
  • 了解RabbitMQ中的Exchange:深入解析与实践应用
            在分布式系统设计中,消息队列(MessageQueue)扮演着至关重要的角色,而RabbitMQ作为开源消息代理软件的佼佼者,以其高性能、高可用性和丰富的功能特性,成为了众多开发者的首选。在RabbitMQ的核心组件中,Exchange(交换机)是一个不可或缺的部分,它负责接收生产者发送的消息,......
  • RabbitMQ(二)
    永远的"HelloWorld"一、目标二、具体操作1、创建Java工程2、发送消息①Java代码②查看效果3、接收消息①Java代码②控制台打印③查看后台管理界面一、目标生产者发送消息,消费者接收消息,用最简单的方式实现。官网说明参见下面超链接:RabbitMQtutorial-“Hello......
  • MQTT和传统消息队列(RabbitMQ,RocketMQ,Kafka)的区别
    适用场景选择哪种协议取决于具体的应用需求。如果需要适用于大量传感器和控制设备之间的通信,且网络环境不稳定或需要节省带宽资源,MQTT是一个不错的选择。而如果需要在浏览器和服务端之间建立实时双向通信,且对实时性和双向交互有较高要求,WebSocket可能更加适合。   产......
  • 招行面试:RocketMQ、Kafka、RabbitMQ,如何选型?
    本文原文链接文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完......
  • C# 队列的各种使用方法 private static ConcurrentQueue
            在C#中,ConcurrentQueue<T>是一个线程安全的先进先出(FIFO)集合,它位于System.Collections.Concurrent命名空间中。它非常适合在多线程环境中使用,因为它提供了一些原子操作来确保线程安全。以下是一些常见的ConcurrentQueue<T>使用方法,以ConcurrentQueue<st......
  • C#中的Queue与ConcurrentQueue:区别与适用场景
    在C#中,Queue<T>和ConcurrentQueue<T>是两种不同类型的队列,它们有不同的用途和特性。以下是它们之间的主要区别以及何时使用ConcurrentQueue<T>的详细解释。1.主要区别 1.线程安全性:  Queue<T>:不是线程安全的。如果在多线程环境中使用,需要额外的同步机制(如锁)来避免数据......
  • nvim番外之将配置的插件管理器更新为lazy
    在很久以前我写过关于nvim配置的文章,里面推荐使用packer作为插件管理器。但是在一年多以前,packer的仓库中出现这么一段文字Thisrepositoryiscurrentlyunmaintained.Forthetimebeing(asofAugust,2023),itisrecommendedtouseoneofthefollowingpluginmanag......