> 技术文档 > 详解RabbitMQ高级特性之TTL

详解RabbitMQ高级特性之TTL

目录

TTL

添加配置

常量类

消息的TTL

声明队列和交换机并绑定二者关系

编写生产消息代码

生产消息

队列的TTL

声明队列和交换机并绑定二者关系

编写生产消息代码

生产消息(消息无TTL)

生产消息(消息有TTL)

消息的TTL和队列的TTL


TTL

TTL(Time to Live, 过期时间), 即过期时间. RabbitMQ可以对消息和队列设置TTL.
当消息到达存活时间之后, 还没有被消费, 就会被⾃动清除。

咱们在⽹上购物, 经常会遇到⼀个场景, 当下单超过24⼩时还未付款, 订单会被⾃动取消
还有类似的, 申请退款之后, 超过7天未被处理, 则⾃动退款。

添加配置
spring: application: name: rabbit-extensions-demo rabbitmq: addresses: amqp://study:study@47.98.109.138:5672/extension
常量类
public class Constants { //ttl public static final String TTL_QUEUE = \"ttl.queue\"; public static final String TTL_QUEUE2 = \"ttl2.queue\"; public static final String TTL_EXCHANGE = \"ttl.exchange\";}
消息的TTL
声明队列和交换机并绑定二者关系
import org.springframework.amqp.core.*;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import rabbitextensionsdemo.constant.Constants;@Configurationpublic class RabbitMQConfig { @Bean(\"ttlQueue\") public Queue ttlQueue(){ return QueueBuilder.durable(Constants.TTL_QUEUE).build(); } @Bean(\"ttlExchange\") public DirectExchange ttlExchange(){ return ExchangeBuilder.directExchange(Constants.TTL_EXCHANGE).build(); } @Bean(\"ttlBinding\") public Binding ttlBinding(@Qualifier(\"ttlQueue\") Queue queue, @Qualifier(\"ttlExchange\") Exchange exchange){ return BindingBuilder.bind(queue).to(exchange).with(\"ttl\").noargs(); }}
编写生产消息代码
import org.springframework.amqp.rabbit.core.RabbitTemplate;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import rabbitextensionsdemo.constant.Constants;@RequestMapping(\"/producer\")@RestControllerpublic class ProducerController { @Resource(name = \"rabbitTemplate\") private RabbitTemplate rabbitTemplate; @RequestMapping(\"/ttl\") public String ttl() { System.out.println(\"ttl...\"); rabbitTemplate.convertAndSend(Constants.TTL_EXCHANGE, \"ttl\", \"ttl test 30s...\", message -> { message.getMessageProperties().setExpiration(\"30000\"); //单位: 毫秒, 过期时间为30s return message; }); rabbitTemplate.convertAndSend(Constants.TTL_EXCHANGE, \"ttl\", \"ttl test 10s...\", message -> { message.getMessageProperties().setExpiration(\"10000\"); //单位: 毫秒, 过期时间为10s return message; }); return \"消息发送成功\"; }}
生产消息

我们可以看到,生产的两条消息的确消失了,但是耗时30秒,这是为什么呢?

原因是因为设置消息的TTL,哪怕消息过期了,也不会立即删除,而是在将消息投递给消费者之前进行判定。

队列的TTL
声明队列和交换机并绑定二者关系
import org.springframework.amqp.core.*;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import rabbitextensionsdemo.constant.Constants;@Configurationpublic class RabbitMQConfig { @Bean(\"ttlQueue2\") public Queue ttlQueue2(){ return QueueBuilder.durable(Constants.TTL_QUEUE2).ttl(20000).build(); //设置队列的ttl为20s } @Bean(\"ttlExchange\") public DirectExchange ttlExchange(){ return ExchangeBuilder.directExchange(Constants.TTL_EXCHANGE).build(); } @Bean(\"ttlBinding2\") public Binding ttlBinding2(@Qualifier(\"ttlQueue2\") Queue queue, @Qualifier(\"ttlExchange\") Exchange exchange){ return BindingBuilder.bind(queue).to(exchange).with(\"ttl\").noargs(); }}
编写生产消息代码
import org.springframework.amqp.rabbit.core.RabbitTemplate;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import rabbitextensionsdemo.constant.Constants;@RequestMapping(\"/producer\")@RestControllerpublic class ProducerController { @Resource(name = \"rabbitTemplate\") private RabbitTemplate rabbitTemplate; @RequestMapping(\"/ttl\") public String ttl() { System.out.println(\"ttl...\"); rabbitTemplate.convertAndSend(Constants.TTL_EXCHANGE, \"ttl\", \"ttl test 30s...\", message -> { message.getMessageProperties().setExpiration(\"30000\"); //单位: 毫秒, 过期时间为30s return message; }); return \"消息发送成功\"; } @RequestMapping(\"/ttl2\") public String ttl2() { System.out.println(\"ttl2...\"); //发送普通消息 rabbitTemplate.convertAndSend(Constants.TTL_EXCHANGE, \"ttl\", \"ttl test...\"); return \"消息发送成功\"; }}
生产消息(消息无TTL)

我们可以看到,虽然没有给消息设置TTL,但是给ttl2.queue队列设置了20秒的TTL,20秒过后,ttl2.queue队列中的消息消失了。

生产消息(消息有TTL)

此时我们可以看到,20秒之后,消息消失了,我们给队列设置的TTL为20秒,给消息设置的TTL为30秒,最终消息的TTL 为 min(消息的TTL,队列的TTL)。

消息的TTL和队列的TTL

设置队列TTL属性的⽅法, ⼀旦消息过期, 就会从队列中删除
设置消息TTL的⽅法, 即使消息过期, 也不会⻢上从队列中删除, ⽽是在即将投递到消费者之前进⾏判定的.

为什么这两种⽅法处理的⽅式不⼀样?
因为设置队列过期时间, 队列中已过期的消息肯定在队列头部, RabbitMQ只要定期从队头开始扫描是否有过期的消息即可.
⽽设置消息TTL的⽅式, 每条消息的过期时间不同, 如果要删除所有过期消息需要扫描整个队列, 所以不如等到此消息即将被消费时再判定是否过期, 如果过期再进⾏删除即可.