延时队列(RabbitMQ)

freps / 2024-11-17 / 原文

1.概述

延时任务,也叫延迟任务

延迟队列:没有固定的开始时间,它常常是由一个事件触发的,而在这个事件触发之后的一段时间内触发另一个事件,任务可以立即执行,也可以延迟。

2.技术选型

RabbitMQ(死信交换机)实现方式 TTL+死信交换机

1.概述

死信队列:存放死信的队列

死信交换机: 绑定死信队列的交换机

2.成为死信的几种情况

消费者使用 basic.reject 或 basic.nack 声明消费失败,并且消息的 requeue 参数设置为false - 消费者消费消息失败,并且不把消息重回队列

消息设置了过期时间,或者消息存放的队列设置了过期时间,超过时间无人消费 - 消息和队列如果同时都设置了过期时间,以时间短的为准

要投递的队列消息满了,无法投递

3.死信交换机

1.概述

如果这个包含死信的队列配置了 dead-letter-exchange 属性,指定了一个交换机,那么正常队列中的死信就会投递到这个交换机中,而这个交换机称为 死信交换机 (Dead Letter Exchange,检查DLX)。

2.死信的路由过程

1、消费者拒绝消费消息

2、队列绑定了死信交换机

3、死信队列有绑定的死信交换机

实现上述功能的条件

1、死信交换机的名称

2、死信交换机与死信队列绑定的 RoutingKey

3.TTL

1.概述

超时未消费,消息变成死信的两种情况
1、消息所在的队列设置了超时时间
2、消息本身设置了超时时间
如果两者都设置了,以短的时间为优先

2.原理图

4.延时队列

1、声明死信交换机和死信队列

2、声明普通交换机和普通队列、绑定关系

3、发消息

不指定消息过期时间

指定消息过期时间

DelayExchange插件

普通死信队列去实现延时队列会有一种问题,这种问题就是假如说现在有两个消息都存在那个被消费者监听的死信队列中,因为他们是队列所以他们是有顺序的,如果说第一个发过来的消息的生效时间别第二个消息晚那么这个死信队列就会被阻塞,导致第二个消息即使到了生效时间也没有生效。

使用这个DelayExchange插件可以解决这种问题。

1.概述

因为延迟队列的需求非常多,所以RabbitMQ的官方也推出了一个插件,原生支持延迟队列效果

2.官网

https://blog.rabbitmq.com/posts/2015/04/scheduling-messages-with-rabbitmq

3.安装

自行查资料安装

4.原理

DelayExchange需要将一个交换机声明为delayed类型。

发送消息到delayExchange时的执行过程

  • 接收消息
  • 判断消息是否具备x-delay属性
  • 如果有x-delay属性,说明是延迟消息,持久化到硬盘,读取x-delay值,作为延迟时间
  • 返回routing not found结果给消息发送者
  • x-delay时间到期后,重新投递消息到指定队列

5.实现

1、声明DelayExchange交换机、

注解方式【推荐】

Bean方式

2、生产者发送消息