RabbitMQ------持久化(三)
默认情况下,RabbitMQ退出或由于某种原因崩溃时,它忽视队列和消息,除非告知它不要这么做。确保消息不要丢失需要做两件事:将消息和队列都标记为持久化。
队列如何实现持久化
如果要实现队列持久化,需要在声明队列的时候,把durable的参数设置为持久化。
boolean durable = true;
//产生一个队列 声明一个队列
channel.queueDeclare(QUEUE_NAME, durable, false, false, null);
在监控界面 Features表格中,会显示D,代表已持久化。
这时候即使重启MQ,持久化队列还是存在。
注意:如果如果之前声明的队列不是持久化,需要将原队列删除,或者重新创建一个持久化的队列,不然会出现错误。
消息持久化
消息持久化同样是修改生产者的代码,对发消息的第三个参数进行修改。
props = MessageProperties.PRESISTENT_TEXT_PLAN添加这个属性。将消息保存到磁盘。
//1.发送到哪个交换机
//2.路由的key值是哪个,本质上是队列名称
//3.其他参数信息,消息的属性
//4.发送的消息的消息体 byte
//channel.basicPublish("",QUEUE_NAME,null,message.getBytes());
channel.basicPublish("",QUEUE_NAME,MessageProperties.PRESISTENT_TEXT_PLAN,message.getBytes("UTF-8"));
将消息标记为持久化,并不能完全保证不会丢失消息。会存在当消息刚准备保存到磁盘时,但还没存储完,消息再缓存的一个间隔点。此时并没有真正写入磁盘,持久性保证不强。但是对于简单任务队列而言,已经绰绰有余。有更加强力的持久化策略,后续发布确认章节学习。
不公平分发(更加高效)
RabbitMQ默认是轮训分发,但是在某些场景下不是特别适合,比如一个消费者,处理的快,一个处理的慢。这时候轮训分发就会处于空闲状态。
为了避免这种情况,在消费者接收消息时,在信道设置参数。设置参数channel.basicQos(1);
设置0或者不设置,则默认轮训分发。
在消费者位置进行设置
//设置不公平分发
int prefetchCount = 1;
channel.basicQos(prefetchCount);
//设置手动应答
Boolean autoAck = false;
channel.basicConsume(QUEUE_NAME,autoAck,deliverCallback,cancelCallback);
预取值(perfetch)
指定消费者消费多少条数据。提前设置在信道中。
prefetchCount 设置为0,轮训分发
设置为1,则不公平分发
设置大于1,则是预取值。设定消费者消费多少条,(相当于设置消费者最大小消费数)
在管理页面中,Prefetch列下能看到,设置的预取值。
//设置不公平分发
//int prefetchCount = 1;
channel.basicQos(prefetchCount);
//设置手动应答
Boolean autoAck = false;
channel.basicConsume(QUEUE_NAME,autoAck,deliverCallback,cancelCallback);