RabbitMQ实现延时队列

什么是延时队列

指消息进入队列后不会立即被消费,可以被延迟一定的时间,再进行消费.RabbitMQ没有提供延迟队列功能,但是可以使用TTL+DLX来实现延迟队列效果

使用场景

电商平台下单后,30分钟未支付,取消订单回滚库存;新用户注册成功一周后,发送问候短信等等.

延时队列实现

模拟电商平台下单后,30分钟后未支付,取消订单回滚库存
在这里插入图片描述

创建配置类

@Configuration
public class DelayConfig {

    /**
     * 创建一个正常的队列
     *
     * @return
     */
    @Bean
    public Queue createNormalQueue() {
        return QueueBuilder.durable("order_queue").build();
    }

    /**
     * 创建一个死信队列
     *
     * @return
     */
    @Bean
    public Queue createDeadQueue() {
        return QueueBuilder.durable("order_dead_queue")
                .withArgument("x-dead-letter-exchange", "order_dead_exchange") //设置死信交换机
                .withArgument("x-dead-letter-routing-key", "order_dead")//设置死信路由key
                .withArgument("x-message-ttl", 30000)// 队列中消息30秒过期
                .build();
    }

    /**
     * 创建一个正常的交换机
     *
     * @return
     */
    @Bean
    public DirectExchange createNormalExchange() {
        return new DirectExchange("order_exchange");
    }

    /**
     * 创建死信交换机
     *
     * @return
     */
    @Bean
    public DirectExchange createDeadExchange() {
        return new DirectExchange("order_dead_exchange");
    }

    /**
     * 创建绑定:将正常队列绑定到死信交换机上面
     *
     * @return
     */
    @Bean
    public Binding createDeadBinding(@Qualifier(value = "createNormalQueue") Queue queue,
                                     @Qualifier(value = "createDeadExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("order_dead");
    }

    /**
     * 创建绑定:将死信队列绑定到正常的交换机上面
     *
     * @return
     */
    @Bean
    public Binding binding(@Qualifier(value = "createDeadQueue")Queue queue,
                           @Qualifier(value = "createNormalExchange")DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("order");
    }
}

创建监听类

@Component
public class DelayListener {


    @RabbitListener(queues = "order_queue")
    public void listener(Message message, Channel channel, String msg) throws IOException {
        // 模拟业务代码执行
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(simpleDateFormat.format(new Date()) + "收到消息:" + msg);
        System.out.println("检查订单是否付款操作开始::没有支付就取消订单,回滚库存");
        // 签收消息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
}

创建controller用于测试

@RestController
public class DelayController {

    @Autowired
    RabbitTemplate rabbitTemplate;

    @GetMapping(value = "/send")
    public void send(){
        // 模拟业务代码执行
        String orderId = UUID.randomUUID().toString().replace("-","");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(simpleDateFormat.format(new Date())+"创建订单:"+orderId);
        // 通过正常的交换机和routingKey把orderId发送到死信队列
        rabbitTemplate.convertAndSend("order_exchange","order",orderId);
    }
}

注意

  • 为了方便测试,我在配置类中的死信队列消息过期时间设置的是30秒,再真实的场景中根据自己的需求来就好了.
  • 发送消息要发送给order_dead_queue(死信队列),监听要监听order_queue(正常队列)

测试

http://localhost:18081/send:再发出信息后,延迟了30秒后,消费到了信息
在这里插入图片描述

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.番茄炒蛋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值