.net RabbitMQ之CreateBasicProperties:Lazy Queue,Persistent Message

本文介绍如何在RabbitMQ中实现消息持久化,确保服务重启后消息不丢失,以及LazyQueue的使用方法,减少内存消耗,适合硬件内存不足的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注:以下程序使用C#实现

我们在使用RabbitMQ发送消息到队列之后,在某些场景下,我们希望当消息没有被消费时,如果系统发生故障停止或者我们手动重启服务之后,消息仍然存在队列之中,下面我们看一下普通的使用场景:

var channel=connection.CreateModel();
channel.QueueDeclare("mytest",false,false,false,null);
channel.QueueBind("mytest",string.Empty,"",null);
for(var i=0;i<10;i++){
channel.BasicPublish(string.Empty,"mytest",null,Encoding.UTF8.GetBytes("你好"));
}

上面代码是我们往mytest队列中塞了10条数据进去,这10条消息并没有被消费,但是当我们重启RabbitMQ之后,会发现,mytest队列中的消息变为NaN了,代表消息已经丢失了,在某些时候,由于重启服务而丢失消息,是我们不希望看到的

解决办法:

在程序中使用CreateBasicProperties方法,通过该方法创建一个属性实例,给实例的Persistent字段赋值为true即可

var channel=connection.CreateModel();
channel.QueueDeclare("mytest",false,false,false,null);
channel.QueueBind("mytest",string.Empty,"",null);
var properties=channel.CreateBasicProperties();
properties.Persistent=true;
for(var i=0;i<10;i++){
channel.BasicPublish(string.Empty,"mytest",properties,Encoding.UTF8.GetBytes("你好"));
}

下面介绍一下RabbitMQ中的Lazy Queue用法。注:LazyQueue就是将消息写入磁盘,只有用到的时候,才会写入内存

如果我们采用Lazy Queue+InMemory也就是配置了LazyQueue并且properties.Persistent=false;

就是消息不写入内存,写入磁盘

var channel=connection.CreateModel();
//使用方法
channel.QueueDeclare("mytest",false,false,false,new Dictionary<string,object>{
{"x-queue-mode","lazy"}//设置为懒队列
});
channel.QueueBind("mytest",string.Empty,"",null);

for(var i=0;i<100000;i++){
//注意!以下的msg数据非常大,每个msg高达百兆
var msg=string.Format("{0}测试",string.join(",",Enumrable.Range(1,100000)));
channel.BasicPublish(string.Empty,"mytest",null,Encoding.UTF8.GetBytes(msg));
}

这样发送消息,我们会发现,内存的大小几乎没有改变,这说明Lazy确实不会将消息写入内存,而是临时存储在磁盘上,但是这种写法会有问题,就是重启服务之后,消息会丢失。

为了不丢失消息,我们需要采用这种写法 Lazy Queue+Disk

var channel=connection.CreateModel();
//添加下面两句
var properties=channel.BasicCreateProperties();
properties.Persistent=true;
//使用方法
channel.QueueDeclare("mytest",false,false,false,new Dictionary<string,object>{
{"x-queue-mode","lazy"}//设置为懒队列
});
channel.QueueBind("mytest",string.Empty,"",null);

for(var i=0;i<100000;i++){
//注意!以下的msg数据非常大,每个msg高达百兆
var msg=string.Format("{0}测试",string.join(",",Enumrable.Range(1,100000)));
channel.BasicPublish(string.Empty,"mytest",null,Encoding.UTF8.GetBytes(msg));
}

这样,内存既不会暴增,也能将消息持久化

如果是Default Queue+InMemory方法

var channel=connection.CreateModel();

//使用方法
channel.QueueDeclare("mytest",false,false,false,null);
channel.QueueBind("mytest",string.Empty,"",null);

for(var i=0;i<100000;i++){
//注意!以下的msg数据非常大,每个msg高达百兆
var msg=string.Format("{0}测试",string.join(",",Enumrable.Range(1,100000)));
channel.BasicPublish(string.Empty,"mytest",null,Encoding.UTF8.GetBytes(msg));
}

这种方式内存会暴增,并且消息不会持久化到磁盘

我们可以采用Default Queue+Disk方式,将消息持久化到磁盘

var channel=connection.CreateModel();
//添加下面两句
var properties=channel.BasicCreateProperties();
properties.Persistent=true;
//使用方法
channel.QueueDeclare("mytest",false,false,false,null);
channel.QueueBind("mytest",string.Empty,"",null);

for(var i=0;i<100000;i++){
//注意!以下的msg数据非常大,每个msg高达百兆
var msg=string.Format("{0}测试",string.join(",",Enumrable.Range(1,100000)));
channel.BasicPublish(string.Empty,"mytest",null,Encoding.UTF8.GetBytes(msg));
}

但是需要注意的是,这种方式,内存也会暴增

综上所述,如果我们的消息不需要相应非常快,并且硬件内存不足时,可以采用Lazy Queue+Disk方式,如果时其它情况,则需另行讨论

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值