RabbitMQ消息TTL

说明

举个例子:在电商平台上购买一个商品,但是下单了还没付款。系统提示会为你保留一段时间,比如 15 分钟,超过时间后未支付,订单就会被取消掉。

实现这个功能,一个笨拙的方法就是用定时任务,每分钟扫描下所有未付款的订单,判断是否到期。如果到期了,就删除订单。这种方式效率就很低下,做了很多无用功,另一种方法,你就可以使用 RabbitMQ 的 TTL 机制+死信队列来处理。

TTL机制

TTL,全称是 Time to Live,也就是过期时间。RabbitMQ 可以对消息或者队列设置过期时间。通过设置过期时间,如果消息没有消费,到期了就会被处理掉。这样在一个程度上就可以防止 MQ 的消息堆积问题。

  • 给队列设置过期时间,那就是队列中所有消息都有相同的过期时间,不管是早入队的消息,还是晚入队的消息,只要队列的过期时间一到,消息都会被处理掉。
  • 给消息设置过期时间,那就是每条消息的过期时间就都不一样了。
  • 给队列或者消息都设置过期时间,那过期的时间就以这两个时间中较小的为准。队列没到期,某条消息到期了,那这条消息被处理掉。队列到期,那就是覆巢之下焉有完卵了。

那到期了,消息是怎么被处理掉的?它们会变成 “死信”(死亡的消息,Dead Message),放到死信队列中,消费者默认就无法再收到这消息。但死信也是可以被取出来消费的。

默认情况下,如果不设置 TTL,消息就永不过期。如果 TTL 设置为 0,那表示消息要直接投递给消费者,否着消息就会被丢弃掉。

设置方法

设置队列属性

在 queue.declare 方法中加入 x-message-ttl 参数,单位为 ms:

Map<String, Object> argss = new HashMap<String, Object>(); argss.put("x-message-ttl",6000); channel.queueDeclare(queueName, durable, exclusive, autoDelete, argss);

设置消息属性

针对每条消息设置 TTL 的方法是在 basic.publish 方法中加入 expiration 的属性参数,单位为 ms。

AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder(); builder.expiration("6000"); AMQP.BasicProperties properties = builder.build(); channel.basicPublish(exchangeName, routingKey, mandatory, properties, "ttlTestMessage".getBytes());