头图

死信队列

ttl

ttl(time to live),消息存活时间

RabbitMQ支持两种ttl设置:

  • 整个队列进行配置ttl,所有被投递到该队列的消息都最多不会存活超过N
  • 单独消息进行配置ttl

如果同时配置了队列的TTL和消息的TTL,那么较小的那个值将会被使用。

死信消息

以下3种情况消息出现死信:

  • 消费者拒收消息(basic.reject/ basic.nack) ,并且没有重新入队 requeue=false
  • 消息在队列中未被消费,且超过队列或者消息本身的过期时间TTL(time-to-live)
  • 队列的消息长度达到极限

出现死信时,此队列绑定了死信交换机,死信消息会路由到死信队列中

死信交换机DLX

死信交换机和死信队列的声明,与普通的交换机、队列没有任何差别
不过是在普通队列声明时指定了如下属性:

Map<String, Object> args = new HashMap<>(3);
//消息过期后,进入到死信交换机
args.put("x-dead-letter-exchange", "指定的死信交换机的名称");

消息进入死信队列后,我们依然可以对监听,做一些特殊处理。

比如:订单在十分钟之内未支付则自动取消。

我们可以设置队列的ttl为10min,待支付订单的id作为消息放入其中;同时绑定死信队列,然后消费者监听死信队列。
这样待消息超时时,消息会进入死信队列并被消费者获取;消费者完成订单取消逻辑即可。

延时队列

再看ttl

如果设置了队列的ttl属性,那么一旦消息过期,就会被队列丢弃;而消息层面的ttl,则有些玄妙。
比如一条消息的ttl很短,但前一条消息ttl却很长——这种情况即使本消息过期了也不会马上丢弃。也就是说,消息层面的超时时间,会受队列的消息堆积情况影响

那么不固定的延时情况,通过死信队列实现会有问题

比如这个需求:预定会议室成功后开会前10分钟通知。

  • 采用在队列上设置ttl的方式,由于时间的不固定,必然会产生超多队列
  • 采用在消息上设置ttl的方式,由于消息堆积通知会不准,甚至无法通知

那如何解决这个问题呢?安装rabbitmq_delayed_message_exchange插件即可。

生产者关键代码:

Map<String, Object> args = new HashMap<String, Object>();
args.put("x-delayed-type", "direct");

channel.exchangeDeclare(交换机名称, "x-delayed-message", true, false, args);

附录

P6-P7知识合辑


青鱼
268 声望25 粉丝

山就在那里,每走一步就近一些