# 持久化
# 概念
看到了如何处理任务不丢失的情况,但是如何保障当 RabbitMQ 服务停掉以后消 息生产者发送过来的消息不丢失。
默认情况下 RabbitMQ 退出或由于某种原因崩溃时,它忽视队列 和消息,除非告知它不要这样做。
确保消息不会丢失需要做两件事:我们需要将队列和消息都标 记为持久化。
# 队列如何实现持久化
之前我们创建的队列都是非持久化的,rabbitmq 如果重启的化,该队列就会被删除掉,如果 要队列实现持久化 需要在声明队列的时候把 durable 参数设置为持久化
警告
如果之前声明的队列不是持久化的,需要把原先队列先删除(在可视化界面点击队列名称,进去后点击Delete),或者重新 创建一个持久化的队列,不然就会出现错误
以下为控制台中持久化与非持久化队列的 UI 显示区,这个时候即使重启 rabbitmq 队列也依然存在
# 消息实现持久化
要想让消息实现持久化需要在消息生产者修改代码,MessageProperties.PERSISTENT_TEXT_PLAIN 添 加这个属性。
将消息标记为持久化并不能完全保证不会丢失消息。尽管它告诉 RabbitMQ 将消息保存到磁盘,但是 这里依然存在当消息刚准备存储在磁盘的时候 但是还没有存储完,消息还在缓存的一个间隔点。
此时并没 有真正写入磁盘。持久性保证并不强,但是对于我们的简单任务队列而言,这已经绰绰有余了。如果需要 更强有力的持久化策略,参考后边课件发布确认章节。
# 代码
# 生产者
import com.gao.rabbitmq.utils.RabbitMQUtils;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.MessageProperties;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* author: 高亮
* time: 2022/7/5
* description: 消息应答不丢失,生产者
*/
@Slf4j
public class Producer_ACK {
private static final String ACK_QUEUE = "ack_queue";
public static void main(String[] args) throws IOException {
Channel channel = RabbitMQUtils.getChannel();
channel.queueDeclare(ACK_QUEUE,false,false,true,null);
for (int i = 0; i < 20; i++) {
byte[] message = ("ack message" + i).getBytes(StandardCharsets.UTF_8);
//MessageProperties.PERSISTENT_TEXT_PLAIN 设置生产者发送消息为持久化消息(要求保存到磁盘上)保存在内存中
channel.basicPublish("", ACK_QUEUE, MessageProperties.PERSISTENT_TEXT_PLAIN, message);
}
log.info("发送完毕");
}
}