第7章 RabbitMQ延迟消息
1.死信队列
官方文档:
https://www.rabbitmq.com/dlx.html
阿里云介绍:
参考博客:
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的时间。这样就实现了延迟队列的效果。
- 第二种:利用延迟插件实现
虽然基于死信队列可以实现延迟消息,但是配置起来比较复杂,因此RabbitMQ官方提供了一个专门的延迟插件来实现相同的效果。
官方文档说明:
https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/
安装部署:
#查看插件目录 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