RabbitMQ如何实现延迟队列?(转)
什么是延迟队列
延迟队列存储的对象肯定是对应的延迟消息,所谓”延迟消息”是指当消息被发送以后,并不想让消费者立即拿到消息,而是等待指定时间后,消费者才拿到这个消息进行消费。
场景一:在订单系统中,一个用户下单之后通常有30分钟的时间进行支付,如果30分钟之内没有支付成功,那么这个订单将进行一场处理。这是就可以使用延迟队列将订单信息发送到延迟队列。
场景二:用户希望通过手机远程遥控家里的智能设备在指定的时间进行工作。这时候就可以将用户指令发送到延迟队列,当指令设定的时间到了再将指令推送到只能设备。
RabbitMQ怎么实现延迟队列
AMQP协议,以及RabbitMQ本身没有直接支持延迟队列的功能,但是可以通过TTL和DLX模拟出延迟队列的功能。
TTL(Time To Live)
RabbitMQ可以针对Queue和Message设置 x-message-tt,来控制消息的生存时间,如果超时,则消息变为dead letter
RabbitMQ针对队列中的消息过期时间有两种方法可以设置。
- A: 通过队列属性设置,队列中所有消息都有相同的过期时间。
- B: 对消息进行单独设置,每条消息TTL可以不同。
如果同时使用,则消息的过期时间以两者之间TTL较小的那个数值为准。消息在队列的生存时间一旦超过设置的TTL值,就成为dead letter
详细可以参考:RabbitMQ之TTL(Time-To-Live 过期时间)
DLX (Dead-Letter-Exchange)
RabbitMQ的Queue可以配置x-dead-letter-exchange 和x-dead-letter-routing-key(可选)两个参数,如果队列内出现了dead letter,则按照这两个参数重新路由。
- x-dead-letter-exchange:出现dead letter之后将dead letter重新发送到指定exchange
- x-dead-letter-routing-key:指定routing-key发送
队列出现dead letter的情况有:
- 消息或者队列的TTL过期
- 队列达到最大长度
- 消息被消费端拒绝(basic.reject or basic.nack)并且requeue=false
利用DLX,当消息在一个队列中变成死信后,它能被重新publish到另一个Exchange。这时候消息就可以重新被消费。
详细可以参考:RabbitMQ之死信队列
代码示例
首先建立2个exchange和2个queue:
- exchange_delay_begin:这个是producer端发送时调用的exchange, 将消息发送至queue_dealy_begin中。
- queue_delay_begin: 通过routingKey=”delay”绑定exchang_delay_begin, 同时配置DLX=exchange_delay_done, 当消息变成死信时,发往exchange_delay_done中。
- exchange_delay_done: 死信的exchange, 如果不配置x-dead-letter-routing-key则采用原有默认的routingKey,即queue_delay_begin绑定exchang_delay_beghin采用的“delay”。
- queue_delay_done:消息在TTL到期之后,最终通过exchang_delay_done发送值此queue,消费端通过消费此queue的消息,即可以达到延迟的效果。
1. 建立exchange和queue的代码(当然这里可以通过RabbitMQ的管理界面来实现,无需code相关代码):
channel.exchangeDeclare("exchange_delay_begin", "direct", true);
channel.exchangeDeclare("exchange_delay_done", "direct", true);
Map<String, Object> args = new HashMap<String, Object>();
args.put("x-dead-letter-exchange", "exchange_delay_done");
channel.queueDeclare("queue_delay_begin", true, false, false, args);
channel.queueDeclare("queue_delay_done", true, false, false, null);
channel.queueBind("queue_delay_begin", "exchange_delay_begin", "delay");
channel.queueBind("queue_delay_done", "exchange_delay_done", "delay");
2. consumer端代码:
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume("queue_delay_done", false, consumer); while (true) {
QueueingConsumer.Delivery delivery = consumer.nextDelivery();
String msg = new String(delivery.getBody());
System.out.println("receive msg time:" + new Date() + ", msg body:" + msg);
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}
3. producer端代码:设置消息的延迟时间为1min。
AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
builder.expiration("60000");//设置消息TTL
builder.deliveryMode(2);//设置消息持久化
AMQP.BasicProperties properties = builder.build(); String message = String.valueOf(new Date());
channel.basicPublish("exchange_delay_begin","delay",properties,message.getBytes());
在创建完exchange和queue之后,首先执行consumer端的代码,之后执行producer端的代码,待producer发送完毕之后,查看consumer端的输出:
receive msg time:Tue Feb 14 21:06:19 CST 2017, msg body:Tue Feb 14 21:05:19 CST 2017
可以看到延迟1min消费了相关消息。大功告成~
欲了解更多消息中间件的内容,可以关注:消息中间件收录集
参考资料
转自:https://honeypps.com/mq/rabbitmq-how-to-make-delay-queue/
RabbitMQ如何实现延迟队列?(转)的更多相关文章
- SpringBoot | 第三十八章:基于RabbitMQ实现消息延迟队列方案
前言 前段时间在编写通用的消息通知服务时,由于需要实现类似通知失败时,需要延后几分钟再次进行发送,进行多次尝试后,进入定时发送机制.此机制,在原先对接银联支付时,银联的异步通知也是类似的,在第一次通知 ...
- C# RabbitMQ延迟队列功能实战项目演练
一.需求背景 当用户在商城上进行下单支付,我们假设如果8小时没有进行支付,那么就后台自动对该笔交易的状态修改为订单关闭取消,同时给用户发送一份邮件提醒.那么我们应用程序如何实现这样的需求场景呢?在之前 ...
- 【RabbitMQ】一文带你搞定RabbitMQ延迟队列
本文口味:鱼香肉丝 预计阅读:10分钟 一.说明 在上一篇中,介绍了RabbitMQ中的死信队列是什么,何时使用以及如何使用RabbitMQ的死信队列.相信通过上一篇的学习,对于死信队列已经有了更 ...
- 消息队列RabbitMQ(五):死信队列与延迟队列
死信队列 引言 死信队列,英文缩写:DLX .Dead Letter Exchange(死信交换机),其实应该叫做死信交换机才更恰当. 当消息成为Dead message后,可以被重新发送到另一个交换 ...
- RabbitMQ进阶使用-延时队列的配置(Spring Boot)
依赖 MAVEN配置pom.xml <dependency> <groupId>org.springframework.boot</groupId> <art ...
- C#实现rabbitmq 延迟队列功能
最近在研究rabbitmq,项目中有这样一个场景:在用户要支付订单的时候,如果超过30分钟未支付,会把订单关掉.当然我们可以做一个定时任务,每个一段时间来扫描未支付的订单,如果该订单超过支付时间就关闭 ...
- Spring Boot(十四)RabbitMQ延迟队列
一.前言 延迟队列的使用场景:1.未按时支付的订单,30分钟过期之后取消订单:2.给活跃度比较低的用户间隔N天之后推送消息,提高活跃度:3.过1分钟给新注册会员的用户,发送注册邮件等. 实现延迟队列的 ...
- rabbitmq延迟队列demo
1. demo详解 1.1 工程结构: 1.2 pom 定义jar包依赖的版本.版本很重要,rabbit依赖spring,两者必须相一致,否则报错: <properties> <sp ...
- Spring RabbitMQ 延迟队列
一.说明 在实际业务场景中可能会用到延时消息发送,例如异步回调失败时的重发机制. RabbitMQ本身不具有延时消息队列的功能,但是可以通过rabbitmq-delayed-message-excha ...
随机推荐
- Learning a Similarity Metric Discriminatively, with Application to Face Verification
目录 概 主要内容 genuine 和 impostor 文1 文2 Chopra S, Hadsell R, Lecun Y, et al. Learning a similarity metric ...
- 在页面中添加两个 <select> 标签,用来显示年份和月份;同时添加两个 <ul> 标签,一个用来显示星期,另一个用来显示日期 在 JavaScript 脚本中动态添加年份和月份,获取当前日期的年份
查看本章节 查看作业目录 需求说明: 使用 JavaScript 中的 Date 对象,在页面上显示一个万年历.选择不同的年份和月份,在页面中显示当前月的日历 实现思路: 在页面中添加两个 <s ...
- 【MySQL作业】MySQL函数——美和易思字符串函数应用习题
点击打开所使用到的数据库>>> 1.将所有客户的姓名与电话以"-"作为分隔符进行连接显示. 使用 concat(s1,s2,-) 函数将所有客户的姓名与电话以&q ...
- 【】VMware vSphere中三种磁盘规格的解释说明
在VMware vSphere中,不管是以前的5.1版本,或者是现在的6.5版本,创建虚拟机时,在创建磁盘时,都会让选择磁盘的置备类型,如下图所示,分为: 厚置备延迟置零 厚置备置零 Thin Pro ...
- versions-maven-plugin插件批量修改版本号
1.简介 versions-maven-plugin插件可以管理项目版本, 特别是当Maven工程项目中有大量子模块时, 可以批量修改pom版本号, 插件会把父模块更新到指定版本号, 然后更新子模块版 ...
- MongoDB备份与恢复操作
1. 备份和恢复工具参数 * 几个重要参数: * mongodump * --polog:复制mongodump开始到结束过程中的所有oplog并输出到结果中.输出文件位于dump/oplog.bso ...
- python + pymysql连接数据库报“(2003, "Can't connect to MySQL server on 'XXX数据库地址' (timed out)")”
python + pymysql连接数据库报"(2003, "Can't connect to MySQL server on 'XXX数据库地址' (timed out)&quo ...
- PPT文档学习小练习链接
1. <初识PPT2010> https://www.toutiao.com/i6486689592241029645/ 2. <PowerPoint2010实现折线图动态展示> ...
- IntelliJ IDEA最新破解方法
IntelliJ IDEA最新破解方法 首先说下,本人使用idea版本是2021.2.3. 一.下载IDEA(推荐从官网下载) 官网地址:https://www.jetbrains.com/idea/ ...
- 【原创】美团二面:聊聊你对 Kafka Consumer 的架构设计
在上一篇中我们详细聊了关于 Kafka Producer 内部的底层原理设计思想和细节, 本篇我们主要来聊聊 Kafka Consumer 即消费者的内部底层原理设计思想. 1.Consumer之总体 ...