死信队列

引言

死信队列,英文缩写:DLX 。Dead Letter Exchange(死信交换机),其实应该叫做死信交换机才更恰当。

当消息成为Dead message后,可以被重新发送到另一个交换机,这个交换机就是DLX。

总结:其实死信队列就是一个普通的交换机,有些队列的消息成为死信后,(比如过期了或者队列满了)这些死信一般情况下是会被 RabbitMQ 清理的。但是你可以配置某个交换机为此队列的死信交换机,该队列的消息成为死信后会被重新发送到此 DLX 。至于怎么处理这个DLX中的死信就是看具体的业务场景了,DLX 中的信息可以被路由到新的队列。

消息成为死信的三种情况

  • 队列长度到达限制,无法加入新的消息
  • 消费者拒接消费消息,并且不重回队列。该信息会被清除并进入死信队列
  • 原队列存在消息过期设置,消息到达超时时间未被消费

队列如何绑定 DLX

  • x-dead-letter-exchange 指定此队列的死信队列
  • x-dead-letter-exchange 指定此队列向DLX发送死信的routing key,因为这个时候该队列相当于一个生产者,发送消息要指定routing key

实现效果:往一个普通队列添加消息,消息过期成为死信,进入死信队列。死信队列根据配置好的route key 路由到与它绑定的其他普通队列。

  1. 声明死信队列(普通交换机)

        // 声明死信交换机
    @Bean("deadExchange")
    public Exchange deadExchange(){
    return ExchangeBuilder.topicExchange("sb_dead_exchange").durable(true)
    .autoDelete().build();
    }
  2. 声明普通队列,配置它的DLX

        // 声明普通队列,绑定死信队列
    @Bean
    public Queue queue3(){
    Queue build = QueueBuilder.durable("sb_dead_queue").build();
    build.addArgument("x-message-ttl",10000);
    build.addArgument("x-dead-letter-exchange","sb_dead_exchange");
    // 此时队列相当于生产者,因此要指定消息的routing key,死信队列可以更加routing key路由到其他队列
    build.addArgument("x-dead-letter-routing-key","user4.info");
    return build;
    }
    // 绑定此队列和它的交换机
    @Bean
    public Binding exchangQueue3(@Qualifier("queue3")Queue queue,
    @Qualifier("topicExchange") Exchange exchange){
    return BindingBuilder.bind(queue).to(exchange).with("user3.#").noargs();
    }
  3. 绑定死信队列和普通队列,死信队列中的消息会根据路由发送到其他队列

        // 绑定死信队列和普通队列
    @Bean
    public Binding exchangQueue4(@Qualifier("queue2")Queue queue,
    @Qualifier("deadExchange") Exchange exchange){
    return BindingBuilder.bind(queue).to(exchange).with("user4.#").noargs();
    }

    延迟队列

    延迟队列,即消息进入队列后不会立即被消费,只有到达指定时间后,才会被消费。经典的应用场景是下单减库存。

    预扣库存的模式下,我们下单会立刻减库存,但是超过支付时间还没支付的话该订单就会被取消,库存回滚。

    具体实现可以采用定时器的方式,定时检查当前时间与下单时间是否超过上限,比如设置为30min。但是多久执行一次定时任务是个问题,精度大(比如1s执行一次)的话数据库的压力十分大,精度小(比如2min执行一次)的话又会带来误差。

    现在采用的方式是采用延迟队列。RabbitMQ没有提供延迟队列的功能。但是我们能使用死信队列 + TTL 自己实现延迟队列。TTL时间为过期时间(如30min)。

    我们为每条订单信息设置一个过期时间(30min),消息过期后成为死信,自动进入死信队列,死信队列又把消息路由到它绑定的普通队列,库存系统订阅该队列即可在30min后才取出该信息。间接实现了延迟队列的功能

    如此设计库存系统就一定只能在30min后才能从队列中取出订单

消息队列RabbitMQ(五):死信队列与延迟队列的更多相关文章

  1. RabbitMQ 入门教程(PHP版) 延迟队列,延迟任务

    延迟任务应用场景 场景一:物联网系统经常会遇到向终端下发命令,如果命令一段时间没有应答,就需要设置成超时. 场景二:订单下单之后30分钟后,如果用户没有付钱,则系统自动取消订单. 场景三:过1分钟给新 ...

  2. 【RabbitMQ 实战指南】一 延迟队列

    1.什么是延迟队列 延迟队列中存储延迟消息,延迟消息是指当消息被发送到队列中不会立即消费,而是等待一段时间后再消费该消息. 延迟队列很多应用场景,一个典型的应用场景是订单未支付超时取消,用户下单之后3 ...

  3. RabbitMQ 延迟队列,消息延迟推送

    目录 应用场景 消息延迟推送的实现 测试结果 应用场景 目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如: 淘宝七天自动确认收货.在我们签收商品后,物流系统会在七天后延时发送一个消息给 ...

  4. C#实现rabbitmq 延迟队列功能

    最近在研究rabbitmq,项目中有这样一个场景:在用户要支付订单的时候,如果超过30分钟未支付,会把订单关掉.当然我们可以做一个定时任务,每个一段时间来扫描未支付的订单,如果该订单超过支付时间就关闭 ...

  5. 如何用RabbitMQ实现延迟队列

    前言 在 jdk 的 juc 工具包中,提供了一种延迟队列 DelayQueue.延迟队列用处非常广泛,比如我们最常见的场景就是在网购或者外卖平台中发起一个订单,如果不付款,一般 15 分钟后就会被关 ...

  6. RabbitMQ如何实现延迟队列?(转)

    什么是延迟队列 延迟队列存储的对象肯定是对应的延迟消息,所谓"延迟消息"是指当消息被发送以后,并不想让消费者立即拿到消息,而是等待指定时间后,消费者才拿到这个消息进行消费. 场景一 ...

  7. Java 延迟队列使用

    延时队列,第一他是个队列,所以具有对列功能第二就是延时,这就是延时对列,功能也就是将任务放在该延时对列中,只有到了延时时刻才能从该延时对列中获取任务否则获取不到…… 应用场景比较多,比如延时1分钟发短 ...

  8. Dyno-queues 分布式延迟队列 之 基本功能

    Dyno-queues 分布式延迟队列 之 基本功能 目录 Dyno-queues 分布式延迟队列 之 基本功能 0x00 摘要 0x01 Dyno-queues分布式延迟队列 1.1 设计目标 1. ...

  9. Dyno-queues 分布式延迟队列 之 生产消费

    Dyno-queues 分布式延迟队列 之 生产消费 目录 Dyno-queues 分布式延迟队列 之 生产消费 0x00 摘要 0x01 前情回顾 1.1 设计目标 1.2 选型思路 0x02 产生 ...

  10. Dyno-queues 分布式延迟队列 之 辅助功能

    Dyno-queues 分布式延迟队列 之 辅助功能 目录 Dyno-queues 分布式延迟队列 之 辅助功能 0x00 摘要 0x01 前文回顾 0x2 Ack机制 2.1 加入Un-ack集合 ...

随机推荐

  1. 3、Spring教程之IOC创建对象方式

    1.通过无参构造方法来创建 1.User.java public class User { private String name; public User() { System.out.printl ...

  2. .Net5下WebRequest、WebClient、HttpClient是否还存在使用争议?

    WebRequest.WebClient.HttpClient 是C#中常用的三个Http请求的类,时不时也会有人发表对这三个类使用场景的总结,本人是HttpClient 一把梭,也没太关注它们的内部 ...

  3. UML第二部分和创建型模式

    状态机视图通过对每个类的对象的生命期进行建模 描述了对象时间上的动态行为 .状态指就某个特定类而言 对于发生的事件具有相同性质响应的一系列对象值.状态机不但可以描述类的行为 而且可以描述用例 协作和方 ...

  4. Java学习之随机数的用法

    •前言 随机数的产生在一些代码中很常用,也是我们必须要掌握的. 而 Java 中产生随机数的方法主要有三种: new Random() Math.random() currentTimeMillis( ...

  5. webpack核心模块tapable源码解析

    上一篇文章我写了tapable的基本用法,我们知道他是一个增强版版的发布订阅模式,本文想来学习下他的源码.tapable的源码我读了一下,发现他的抽象程度比较高,直接扎进去反而会让人云里雾里的,所以本 ...

  6. 基于react hooks,zarm组件库配置开发h5表单页面

    最近使用React Hooks结合zarm组件库,基于js对象配置方式开发了大量的h5表单页面.大家都知道h5表单功能无非就是表单数据的收集,验证,提交,回显编辑,通常排列方式也是自上向下一行一列的方 ...

  7. Python-Tkinter 使用for循环生成列表式Button及函数调用

    Tkinter是轻量级的图形化界面,在使用中我们可能遇到需要生成一串Button按钮的情况,如图: 如果一个一个操作就太麻烦了,但我们可以通过for循环列表的形式来实现 来看看以下例子: from t ...

  8. OO第四单元作业总结以及课程总结

    第四单元总结--UML 第四单元作业架构分析 第一次作业其实是本单元三次作业中最难的一次.由于第一次是第一次作业,要考虑到搭建框架和设计架构,这次作业的思维性很强.在了解了各个类型元素(Element ...

  9. (一)Struts2框架概述

    一.struts2发展历史 经过很多年发展,Struts1已经成为了高度成熟的框架,但随着时间的发展,Struts1的局限性和缺点不断的暴露出来.      现在Struts已经分化成了两个框架    ...

  10. Java代码格式化规范实践总结

    目标说明 统一良好的代码格式规范可以有效提升开发团队之间的「协作效率」,如果不同的开发团队或者开发人员采用不同的代码格式规范,那么每次Format代码都会导致大量的变化,在Code Review及Me ...