文章目录
0、问题
默认情况下,RabbitMQ 会将接收到的消息保存在内存中,以降低消息收发的延迟。这样会导致两个问题:
- 一旦 MQ 宕机,内存中的消息就会丢失
- 内存空间有限,当消费者故障或处理过慢时,会导致消息积压,引发 MQ 阻塞
1、数据持久化
RabbitMQ 实现数据持久化包括 3 个方面:
- 交换机持久化
- 队列持久化
- 消息持久化
1.1、交换机持久化
● 控制台
将 Durability 选为 Durable。
● 代码
Spring AMPQ 创建交换机时默认就处理成了 持久化的。
// 创建非持久化交换机
FanoutExchange fec = (FanoutExchange)ExchangeBuilder
.fanoutExchange("myJavaFanout2")
.durable(false)
.build();
1.2、队列持久化
● 控制台
将 Durability 选为 Durable。
● 代码
Spring AMPQ 创建队列时默认就处理成了 持久化的。
// 创建持久化队列
Queue durQueue = QueueBuilder.durable("durQueue").build()
// 创建非持久化队列
Queue nonDurQueue = QueueBuilder.nonDurable("nonDurQueue").build()
1.3、消息持久化
● 控制台
- 交换机发消息时 Properties 设置 delivery_mode=2。
- 队列发消息时将 Durability mode 选为 2 - 持久。
● 代码
Spring AMPQ 发送的消息默认就处理成了 持久化的。
// 创建非持久化消息
Message msg = MessageBuilder
.withBody("message".getBytes(StandardCharsets.UTF_8))
.setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT)
.build();
1.4、区别
● 非持久化:
● 持久化:
2、Lazy Queue
从 RabbitMQ 3.6.0 版本开始,增加了 Lazy Queue 概念,也就是 惰性队列。特征如下:
- 接收到消息后直接存入磁盘而非内存(内存中只保留最近的消息,默认2048条)
- 消费者要消费消息时才从磁盘读取并加载到内存
- 支持数百万条的消息存储
注意:在 3.12 版本后,所有队列都是 Lazy Queue 模式,且 不可更改。
3.12前版本拓展:
- 控制台设置惰性队列
- Java 代码
Queue lazyQueue = QueueBuilder
.durable("durQueue")
.lazy() // 开启 Lazy 模式
.build();
@RabbitListener(queuesToDeclare = @Queue(
name = "myQueue666",
durable = "true",
arguments = @Argument(name = "x-queue-mode", value = "lazy")
))
// ...
● Lazy 效果
处理速度显著提升,效果最好。
3、总结
RabbitMQ 如何保证消息的可靠性?
- 首先通过配置可以让交换机、队列一级发送的消息都持久化。这样队列中的消息会持久化到磁盘,MQ 重启消息依然存在。
- RabbitMQ 在 3.6 版本引入了 LazyQueue,并在 3.12 版本后成为队列的默认模式切不可更改。LazyQueue 会将所有消息都持久化。
- 开启持久化和生产者确认时,RabbitMQ 只在消息持久化完成后才会给生产者返回 ACK 回执。