RabbitMQ—队列参数

 在RabbitMQ里面有一些队列参数,在我们的图形化界面可以看到下面这些信息;

一共10个:

  • Message TTL : 消息生存期
  • Auto expire : 队列生存期
  • Max length : 队列可以容纳的消息的最大条数
  • Max length bytes : 队列可以容纳的消息的最大字节数
  • Overflow behaviour : 队列中的消息溢出后如何处理
  • Dead letter exchange : 溢出的消息需要发送到绑定该死信交换机的队列
  • Dead letter routing key : 溢出的消息需要发送到绑定该死信交换机,并且路由键匹配的队列
  • Maximum priority : 最大优先级
  • Lazy mode : 懒人模式
  • Master locator : 

一、Message TTL

 一个队列中的消息,在被丢弃之前能够存活多少毫秒.( key 为 "x-message-ttl").通俗讲就是,队列中的消息的生存周期,单位毫秒.

RabbitMQ可以对消息和队列设置TTL。目前有两种方法可以设置。

  • 第一种方法是通过队列属性设置,队列中所有消息都有相同的过期时间。
  • 第二种方法是对消息进行单独设置,每条消息TTL可以不同。

如果上述两种方法同时使用,则消息的过期时间以两者之间TTL较小的那个数值为准。消息在队列的生存时间一旦超过设置的TTL值,就称为dead message被投递到死信队列, 消费者将无法再收到该消息。

根据官方描述,它有key肯定是一个map键值对,用代码怎么定义呢。我们先对队列设置过期时间

 对消息单独设置过期时间,在业务代码里面实现

 //给消息设置过期时间
        MessagePostProcessor messagePostProcessor=new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setExpiration("5000");  //设置过期时间
                message.getMessageProperties().setContentEncoding("UTF-8");  //设置编码
              return message;
            }
        };
        rabbitTemplate.convertAndSend(exchangeName, routeKey, orderNumer,messagePostProcessor);

设置消息过期和设置队列参数还有一个区别,单独设置消息过期是直接到期删除消息,而队列是打上了个标签TTL,在队列中的消息到期后,之后有个死信队列来接收,而不会直接删除,这是它的好处。

二、Dead letter exchange, Dead letter routing key(死信队列)

官方 : Optional name of an exchange to which messages will be republished if they are rejected or expire.(Sets the "x-dead-letter-exchange" argument.) 

翻译 : 该参数值为一个(死信)交换机的名称,当队列中的消息的生存期到了,或者因长度限制被丢弃时,消息会被推送到(绑定到)这台交换机(的队列中),而不是直接丢掉. 

DLX也是一个正常的交换机,和一般的交换机没有区别,它能在任何的队列上被指定,实际上就是设置某一个队列的属性。当这个队列中存在死信时,Rabbitmq就会自动地将这个消息重新发布到设置的DLX上去,进而被路由到另一个队列,即死信队列。
要想使用死信队列,只需要在定义队列的时候设置队列参数 x-dead-letter-exchange 指定交换机即可。

 Dead letter routing key是在需要routing key的交换机模式里面才需要配置的,如fanout模式就不用配置。 

 注意:如果你之前已经声明了这个队列,这次往队列里面新增了参数再去声明,它是不会去覆盖或者更新的,而是会报错,我们正常需要先删除这个队列,再去重新声明!

 其实死信队列和普通队列是一样的,其实就是把普通队列绑定到过期队列。就相当于删除照片之后会到最近删除里,然后最近删除TTL为30天。死信队列在实际开发中可以用来实现订单超时业务。

可以看一下我在网上找的别人的一个绑定的案例,它的TTL是在消息里单独设置的。

package com.xiaojie.springboot.config;
 
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
 
import java.util.HashMap;
import java.util.Map;
 
/**
 * @author xiaojie
 * @version 1.0
 * @description:死信队列配置
 * @date 2021/10/8 21:07
 */
@Component
public class DLXConfig {
    //定义队列
    private static final String MY_DIRECT_QUEUE = "snail_direct_queue";
    //定义队列
    private static final String MY_DIRECT_DLX_QUEUE = "xiaojie_direct_dlx_queue";
    //定义死信交换机
    private static final String MY_DIRECT_DLX_EXCHANGE = "xiaojie_direct_dlx_exchange";
    //定义交换机
    private static final String MY_DIRECT_EXCHANGE = "snail_direct_exchange";
    //死信路由键
    private static final String DIRECT_DLX_ROUTING_KEY = "msg.dlx";
 
    //绑定死信队列
    @Bean
    public Queue dlxQueue() {
        return new Queue(MY_DIRECT_DLX_QUEUE);
    }
    //绑定死信交换机
    @Bean
    public DirectExchange dlxExchange() {
        return new DirectExchange(MY_DIRECT_DLX_EXCHANGE);
    }
    @Bean
    public Queue snailQueue() {
        Map<String, Object> args = new HashMap<>();
        // 绑定我们的死信交换机
        args.put("x-dead-letter-exchange", MY_DIRECT_DLX_EXCHANGE);
        // 绑定我们的路由key
        args.put("x-dead-letter-routing-key", DIRECT_DLX_ROUTING_KEY);
        return new Queue(MY_DIRECT_QUEUE, true, false, false, args);
    }
    @Bean
    public DirectExchange snailExchange() {
        return new DirectExchange(MY_DIRECT_EXCHANGE);
    }
    //绑定队列到交换机
    @Bean
    public Binding snailBindingExchange(Queue snailQueue, DirectExchange snailExchange) {
        return BindingBuilder.bind(snailQueue).to(snailExchange).with("msg.send");
    }
    //绑定死信队列到死信交换机
    @Bean
    public Binding dlxBindingExchange(Queue dlxQueue, DirectExchange dlxExchange) {
        return BindingBuilder.bind(dlxQueue).to(dlxExchange).with(DIRECT_DLX_ROUTING_KEY);
    }
}

三、Max length

官方 : How many (ready) messages a queue can contain before it starts to drop them from its head.(Sets the "x-max-length" argument.) 

翻译 : 队列可以容纳的消息的最大条数,超过这个条数,队列头部的消息将会被丢弃.

Max length还是跟死信队列有关,超过设置最大长度的消息会被送进死信队列。如:发送了十一条消息,max length=5,超过的六条直接送进死信队列。如果没有死信队列,就直接丢失。

四、Auto expire

官方 : How long a queue can be unused for before it is automatically deleted (milliseconds).(Sets the "x-expires" argument.) 

翻译 : 队列多长时间(毫秒)没有被使用(访问)就会被删除.换个说法就是,当队列在指定的时间内没有被使用(访问)就会被删除.

  @Bean
    public  Queue autoexpirequeue(){
        Map<String, Object> args = new HashMap<String, Object>();
        args.put("x-expires", 1800000);
        return  new Queue("myqueue", false, false, false, args);

    }

五、Maximum priority 

官方 : Maximum number of priority levels for the queue to support; if not set, the queue will not support message priorities.(Sets the "x-max-priority" argument.) 

翻译 : 设置该队列中的消息的优先级最大值.发布消息的时候,可以指定消息的优先级,优先级高的先被消费.如果没有设置该参数,那么该队列不支持消息优先级功能.也就是说,就算发布消息的时候传入了优先级的值,也不会起什么作用.

优先级加载队列上,就是一个优先级队列 【堆,大根堆,小根堆】
1、给队列贴上一个优先级的标签 x-max-priority=10
2、给message打上具体的优先级的value value<=10

 Map<String, Object> args = new HashMap<String, Object>();
        args.put("x-max-priority",10);
return  new Queue("myqueue", false, false, false, args);

六、Lazy mode

官方 : Set the queue into lazy mode, keeping as many messages as possible on disk to reduce RAM usage; if not set, the queue will keep an in-memory cache to deliver messages as fast as possible.(Sets the "x-queue-mode" argument.) 

翻译 : 设置队列为懒人模式.该模式下的队列会先将交换机推送过来的消息(尽可能多的)保存在磁盘上,以减少内存的占用.当消费者开始消费的时候才加载到内存中;如果没有设置懒人模式,队列则会直接利用内存缓存,以最快的速度传递消息.

<think>嗯,用户想了解RabbitMQ队列丢失的原因和解决方法。首先,我得回忆一下之前学过的RabbitMQ相关知识。记得队列的持久化设置很重要,如果队列没有设置为持久化,当节点重启后队列可能丢失。那得确认一下声明队列时是否设置了durable参数为true。不过用户可能没有正确设置这个参数,导致队列在重启后消失。 然后,节点故障或集群配置问题也可能导致队列丢失。比如镜像队列配置不当,如果主节点宕机,而镜像没有正确同步,队列数据可能丢失。需要检查镜像策略,确保有足够的副本和正确的同步策略。比如设置ha-mode和ha-sync-mode参数,确保数据同步完成再确认。 还有自动删除属性,如果队列被声明为auto-delete,当最后一个消费者断开连接时,队列会被自动删除。用户可能在声明队列时误用了这个属性,导致队列意外删除。这时候需要检查队列的auto-delete参数是否设置为false。 资源不足也可能引发问题,比如磁盘空间不足导致RabbitMQ崩溃,队列数据无法保存。需要监控磁盘使用情况,及时清理日志或增加存储空间。 操作失误,比如手动删除队列或误用命令,也是常见原因。可能需要提醒用户谨慎操作,并使用权限控制限制删除操作。 解决方法方面,确保队列持久化,正确配置集群和镜像队列,合理设置资源监控,避免自动删除,以及规范操作流程。需要引用文档中的相关内容,比如引用3提到队列名称的限制,但可能和持久化相关;引用5提到镜像队列的事务和确认机制,确保消息被所有镜像接受,这可能和队列数据同步有关。引用1中的拒绝消息可能不直接相关,但确认机制可能影响消息的持久性。 可能用户遇到的问题是在节点故障后队列不见了,或者配置镜像队列时没有正确同步数据。需要综合这些因素,给出具体步骤,比如检查队列声明参数,配置镜像策略,监控资源等。同时,生成相关问题,帮助用户进一步理解其他可能导致消息丢失的因素,比如消息持久化,网络分区处理等。</think>### RabbitMQ队列丢失的原因及解决方法 #### 一、常见原因分析 1. **队列未持久化** -队列未设置`durable=true`,当节点重启时队列会被删除。例如声明队列时未指定持久化参数: ```python channel.queue_declare(queue="my_queue") # 默认durable=False ``` 此时队列仅存在于内存中[^3]。 2. **节点故障与集群配置问题** - 镜像队列(Mirrored Queue)若未正确配置`ha-mode`,主节点宕机后可能导致数据丢失。例如: ```bash rabbitmqctl set_policy ha-all "^ha\." '{"ha-mode":"all"}' # 需明确同步策略 ``` 若未启用`ha-sync-mode=automatic`,新节点加入时可能无法同步历史数据[^4][^5]。 3. **自动删除属性(auto-delete)** - 队列若声明为`auto-delete=true`,当最后一个消费者断开连接时,队列会被自动删除。 4. **资源不足导致崩溃** - 磁盘空间不足或内存超限时,RabbitMQ可能触发保护机制,强制关闭节点导致队列丢失[^5]。 5. **操作失误** - 手动执行`rabbitmqctl delete_queue`或误用管理界面删除队列--- #### 二、解决方案 1. **声明持久化队列** 确保队列声明时设置`durable=true`,且消息发布时设置`delivery_mode=2`(持久化消息): ```python channel.queue_declare(queue="persistent_queue", durable=True) channel.basic_publish(exchange="", routing_key="persistent_queue", body=message, properties=pika.BasicProperties(delivery_mode=2)) ``` 2. **配置高可用镜像队列** - 使用策略同步数据到多个节点: ```bash rabbitmqctl set_policy ha-two "^mirrored\." '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}' ``` 确保至少两个节点完成数据同步后才确认消息[^4]。 3. **关闭自动删除属性** 声明队列时避免使用`auto-delete=true`: ```python channel.queue_declare(queue="stable_queue", auto_delete=False) ``` 4. **监控资源使用** - 通过`rabbitmqctl status`检查内存和磁盘状态。 - 设置磁盘预警阈值(如`disk_free_limit.absolute=5GB`)。 5. **操作规范与权限控制** - 限制删除队列的权限(通过RabbitMQ权限系统)。 - 使用`Confirm机制`确保消息持久化后再返回确认[^1]。 --- #### 三、验证队列状态 1. 查看队列详情: ```bash rabbitmqctl list_queues name durable auto_delete policy ``` 2. 检查镜像同步状态: ```bash rabbitmqctl list_queues name slave_pids synchronised_slave_pids ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JagTom

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值