举个例子:在电商平台上购买一个商品,但是下单了还没付款。系统提示会为你保留一段时间,比如 15 分钟,超过时间后未支付,订单就会被取消掉。
实现这个功能,一个笨拙的方法就是用定时任务,每分钟扫描下所有未付款的订单,判断是否到期。如果到期了,就删除订单。这种方式效率就很低下,做了很多无用功,另一种方法,你就可以使用 RabbitMQ 的 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());