【RabbitMQ】TTL机制

本文探讨了如何利用RabbitMQ的TTL机制实现订单自动取消功能,详细介绍了TTL的两种设置方式及其应用场景,并通过Spring Boot进行了实例演示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

之前有篇文章说的是:下单但未支付的订单怎么做延迟取消,具体文章链接如下:

【笔记】下单但未支付的订单倒计时自动取消逻辑实现_阿小冰的博客-优快云博客_订单倒计时实现方案【笔记】下单但未支付的订单倒计时自动取消逻辑实现https://blog.youkuaiyun.com/qq_38377525/article/details/124385040这篇文章主要讲了集中常见方案,其中最后一个方案是利用MQ做延迟,只是在上面的文章中没有过多解释,只是提供了思路,那我们这篇文章主要讲一下实现过程

介绍

看图,这是在京东上下的一笔订单,只是订单创建成功了,但未支付,一般来说都是半小时倒计时,京东这里是两个小时,如果两个小时还是没有支付,那这笔订单就会自动取消

RabbitMQ的TTL机制

介绍

TTL,全称Time to Live,翻译过来就是过期时间 

思路 

RabbitMQ可以对消息和队列这两个角度来设置TTL

  1. 通过Queue属性来设置,队列中所有消息都有相同的过期时间
  2. 对消息自身进行单独设置,每条消息的TTL可以不相同

疑问 1

这两个方案能不能一块使用

解答1

可以,的那是如果这两种方法一起使用的话,那TTL就会取这两个方法中较小数值为主要的过期时间

疑问2

为什么要以最小数值为准?

解答2

一般来说,消息在队列中的存在时间只要超过设置的TTL时,就会变成死信。也就是消费者默认就无法在获取到该信息

关于死信相关知识,请移驾到下面的链接~【RabbitMQ】死信队列_阿小冰的博客-优快云博客【RabbitMQ】死信队列https://blog.youkuaiyun.com/qq_38377525/article/details/124987975

设置规则 

  1. 如果不设置TTL,则表示消息不会过期
  2. 如果TTL设置为0的话,就表示除非此时可以直接将消息投递到消费者进行消费,否则该消息会被立即丢弃 

TTL相关的参数单位都是毫秒ms

SpringBoot模拟TTL场景

1、添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2、添加配置

spring.application.name=springboot_rabbitmq
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.virtual-host=/
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.port=5672

3、添加mq配置类

@Configuration
public class RabbitConfig {
    /**
     * 定义TTL,对于该队列中的消息,设置都等待10s
     *
     * @return
     */
    @Bean
    public Queue queueTTLWaiting() {
        Map<String, Object> props = new HashMap<>();
        props.put("x-message-ttl", 10000);
        return new Queue("queue.pay.ttl-waiting", false, false, false, props);
    }

    /**
     * 普通队列,没有过期设置
     * @return
     */
    @Bean
    public Queue queueWaiting() {
        return new Queue("queue.pay.waiting", false, false, false);
    }

    /**
     * 使用该交换器,进来的消息都有相同的过期时间
     * @return
     */
    @Bean
    public Exchange exchangeTTLWaiting() {
        return new DirectExchange("exchange.pay.ttl-waiting", false, false);
    }

    /**
     * 使用该交换器,需要对每个消息设置过期时间
     * @return
     */
    @Bean
    public Exchange exchangeWaiting() {
        return new DirectExchange("exchange.pay.waiting", false, false);
    }

    /**
     * 绑定TTL队列相关配置
     * @return
     */
    @Bean
    public Binding bindingTTLWaiting() {
        return BindingBuilder.bind(queueTTLWaiting()).to(exchangeTTLWaiting()).with("pay.ttl-waiting").noargs();
    }

    /**
     * 正常绑定
     * @return
     */
    @Bean
    public Binding bindingWaiting(){
        return BindingBuilder.bind(queueWaiting()).to(exchangeWaiting()).with("pay.waiting").noargs();
    }
}

4、编写接口

@RestController
public class PayController {
    @Autowired
    private AmqpTemplate amqpTemplate;

    /**
     * 发送一个队列统一过期时间的消息
     *
     * @return
     */
    @RequestMapping("/pay/queue-ttl")
    public String sendMsg() {
        amqpTemplate.convertAndSend("exchange.pay.ttl-waiting", "pay.ttl-waiting", "发送一个TTL的通道消息!");
        return "OK";
    }

    /**
     * 对每个消息设置过期时间
     *
     * @return
     * @throws UnsupportedEncodingException
     */
    @RequestMapping("/pay/msg-ttl")
    public String sendTTLMsg() throws UnsupportedEncodingException {
        MessageProperties properties = new MessageProperties();
        properties.setExpiration("5000");
        Message message = new Message("发送了一个有过期日期的msg".getBytes("utf-8"), properties);
        amqpTemplate.convertAndSend("exchange.pay.waiting", "pay.waiting", message);
        return "msg-ttl-ok";
    }
}

5、测试接口

①/pay/queue-ttl:效果是只要走这个交换器的消息都会设置10s的过期日期

我们请求一下接口,查看一下对应交换器的指标,通过指标图可以看出来

 我们设置的是10s的过期时间,所以过了10s之后,这个数据就会清零

同时在这一列,我们也不难看出,当前观察的这一列是一个TTL队列 


②/pay/msg-ttl:效果是看到一个5s的过期时间的消息

我们请求一下接口,会发现表格中出现了数值,这个是消息数量

 我们设置了大概5s的过期时间,5s之后就清空了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值