跳到主要内容

第7章 RabbitMQ延迟消息

1.死信队列

官方文档:

https://www.rabbitmq.com/dlx.html

阿里云介绍:

https://help.aliyun.com/zh/apsaramq-for-rabbitmq/developer-reference/dead-letter-exchange#63b5e9b0312j7

参考博客:

https://mfrank2016.github.io/breeze-blog/2020/05/04/rabbitmq/rabbitmq-how-to-use-dead-letter-queue/

理想情况下生产者往MQ里发送消息,消费者从MQ里消费消息,消费完之后消息就从MQ里删除。

但是实际工作中可能会出现消费者无法消费消息队列里的数据,如果这些无法消费的数据一直在消息队列里存在,则会导致队列消息被塞满,正常的消息也无法写入了。这种消息就被成为死信

死信(Dead Letter)是指无法被投递到任何一个消费者的消息,如果一个队列里的消息满意以下情况之一就会成为死信

  • 消息达到过期时间,超时无人消费
  • 消息队列满了,生产者无法投递消息
  • 消费者拒收消息

死信交换机(Dead Letter Exchange, DLX)是一个用来接收死信的交换机。在消息队列系统中,可以为队列指定一个死信交换机,当队列中的消息变成死信后,这些消息会被自动路由到指定的死信交换机。从而可以进一步处理这些死信,例如记录日志、警告通知或者进行重试等。

死信队列(Dead Letter Queue, DLQ)则是与死信交换机相连的队列,用于存放死信。实际上,死信队列是普通队列的一种特殊用途,专门用来存储那些无法被正常处理的消息。通过设置死信队列,开发者可以监控和管理这些无法正常处理的消息,从而采取相应的措施,如分析原因、手动干预处理等。

在实际应用中,配置死信交换机和死信队列可以帮助提高系统的可靠性,确保消息处理的完整性,避免因为各种原因导致的消息丢失。例如,在RabbitMQ中,可以通过队列的参数来设置死信交换机,当消息因为上述原因变成死信时,会自动被发送到这个指定的死信交换机,然后根据交换机的类型和绑定规则被路由到一个或多个死信队列中。

对于死信的处理方式大致有以下几种:

  • 丢弃:对于不重要的消息直接丢弃,不做任何处理
  • 入库:将死信消息写入到数据库里,单独处理
  • 监听:消息成为死信后进入死信队列,然后有专门处理异常情况的消费者监听死信队列,做后续处理

2.消息存活时间 TTL

RabbitMQ中可以给消息或者队列设置TTL最大存活时间。

在RabbitMQ中,可以为消息设置TTL,这是通过在消息属性中设置expiration字段来实现的。如果一条消息在设置的TTL时间内没有被消费(即从队列中取出),那么这条消息会过期。过期的消息处理方式取决于队列的配置。如果队列被配置为使用死信交换机(DLX),则过期的消息会成为死信并被路由到指定的死信交换机。如果没有配置死信交换机,那么过期的消息将被队列丢弃。

3.延迟队列

3.1 什么是延迟队列

简单来说就是生产者发送消息之后,并不希望用户马上就接收到消息,而是推迟一段时间之后再消费

3.2 延迟队列使用场景

1. 订单系统中的支付超时处理

在电商平台中,用户下单后通常会有一个支付窗口期,如果在指定时间内未支付,则需要自动取消订单。通过延迟队列,可以在用户下单时发送一个延时消息,如果用户在指定时间内未支付,消息到期后触发取消订单的操作。

2. 定时任务和提醒

延迟队列可以用于实现定时任务,如发送未来某个时间点的提醒通知、会员到期提醒、预约提醒等。这些任务可以在指定时间之前入队,到时间后自动执行。

3. 延迟重试机制

在分布式系统中,某些操作可能因为临时的网络问题或服务不稳定而失败。通过延迟队列,可以实现失败任务的延时重试,而不是立即重试,给系统恢复正常运行提供了缓冲时间。

4. 数据一致性保障

在微服务架构中,服务间的数据同步可能需要一定的时间窗口来保证数据一致性。通过延迟队列,可以延迟处理数据同步操作,确保在处理前所有相关的前置条件都已满足。

5. 过期资源的自动清理

系统中的某些资源如临时文件、缓存数据等可能需要在创建一段时间后自动清理。延迟队列可以用来实现这些资源的到期自动清理机制。

6. 流量控制和削峰填谷

在高并发场景下,可以利用延迟队列对请求进行缓冲,将大量瞬时流量分散到较长的时间窗口中处理,从而减轻后端服务的压力。

7. 事件驱动的业务逻辑

某些业务逻辑可能依赖于时间触发,比如某活动开始前的准备工作、活动结束后的数据处理等。通过延迟队列,可以精确控制这些逻辑执行的时间点。

延迟队列的应用极大地增强了系统的灵活性和可靠性,使得开发者能够以时间为维度控制业务逻辑的执行,满足了复杂场景下的业务需求。

3.3 延迟队列的实现方式

延迟队列实现方式有两种:

  • 第一种:利用死信交换机实现实现原理:生产者投递带有TTL的消息发送给正常的交换机,然后正常的交换机发送给正常的队列,但是这个队列没有消费者,这就会导致此条消息在TTL超时后会成为死信。成为死信后投递给死信交换机,然后延迟消费的队列绑定死信交换机,消费者再绑定这个队列,这样当消费者收到消息时正好已经过了TTL的时间。这样就实现了延迟队列的效果。

image-20240220083903688.png

  • 第二种:利用延迟插件实现

虽然基于死信队列可以实现延迟消息,但是配置起来比较复杂,因此RabbitMQ官方提供了一个专门的延迟插件来实现相同的效果。

官方文档说明:

https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/

https://help.aliyun.com/zh/apsaramq-for-rabbitmq/developer-reference/delayed-messages?spm=a2c4g.11186623.0.preDoc.1b6a5609MWkusy

安装部署:

#查看插件目录 rabbitmq-plugins directories -s

#移动延迟插件到指定目录下 mv rabbitmq_delayed_message_exchange-3.12.0.ez /usr/lib/rabbitmq/lib/rabbitmq_server-3.12.12/plugins/

#激活插件 rabbitmq-plugins enable rabbitmq_delayed_message_exchange

#查看已经激活的插件 rabbitmq-plugins list

更新: 2024-10-04 18:48:06