C#实现rabbitmq 延迟队列功能
最近在研究rabbitmq,项目中有这样一个场景:在用户要支付订单的时候,如果超过30分钟未支付,会把订单关掉。当然我们可以做一个定时任务,每个一段时间来扫描未支付的订单,如果该订单超过支付时间就关闭,但是在数据量小的时候并没有什么大的问题,但是数据量一大轮训数据库的方式就会变得特别耗资源。当面对千万级、上亿级数据量时,本身写入的IO就比较高,导致长时间查询或者根本就查不出来,更别说分库分表以后了。除此之外,还有优先级队列,基于优先级队列的JDK延迟队列,时间轮等方式。但如果系统的架构中本身就有RabbitMQ的话,那么选择RabbitMQ来实现类似的功能也是一种选择。 我们项目中用到了rabbitmq,可以做一个延迟队列完美的解决这个问题。
rabbitmq本身不具有延时消息队列的功能,但是可以通过TTL(Time To Live)、DLX(Dead Letter Exchanges)特性实现。其原理给消息设置过期时间,在消息队列上为过期消息指定转发器,这样消息过期后会转发到与指定转发器匹配的队列上,变向实现延时队列。利用rabbitmq的这种特性,应该有了一个大概的思路。、
网上搜了一下 rabbitmq-delayed-message-exchange 这个插件也可以实现延迟队列的功能。今天介绍的是如何用C#来实现。
首先了解一下TTL和DLX
消息的TTL(Time To Live)
消息的TTL就是消息的存活时间。RabbitMQ可以对队列和消息分别设置TTL。对队列设置就是队列没有消费者连着的保留时间,也可以对每一个单独的消息做单独的设置。超过了这个时间,我们认为这个消息就死了,称之为死信。如果队列设置了,消息也设置了,那么会取小的。所以一个消息如果被路由到不同的队列中,这个消息死亡的时间有可能不一样(不同的队列设置)。这里单讲单个消息的TTL,因为它才是实现延迟任务的关键。
Dead Letter Exchanges
Exchage的概念在这里就不在赘述。一个消息在满足如下条件下,会进死信路由,记住这里是路由而不是队列,一个路由可以对应很多队列。
1. 一个消息被Consumer拒收了,并且reject方法的参数里requeue是false。也就是说不会被再次放在队列里,被其他消费者使用。
2. 上面的消息的TTL到了,消息过期了。
3. 队列的长度限制满了。排在前面的消息会被丢弃或者扔到死信路由上。
Dead Letter Exchange其实就是一种普通的exchange,和创建其他exchange没有两样。只是在某一个设置Dead Letter Exchange的队列中有消息过期了,会自动触发消息的转发,发送到Dead Letter Exchange中去。
首先我建了两个控制台项目一个是生产者,一个是消费者。
生产者代码如下
var factory = new ConnectionFactory() { HostName = "127.0.0.1", UserName = "test", Password = "test" }; using (var connection = factory.CreateConnection()){ while (Console.ReadLine() != null){ using (var channel = connection.CreateModel()){Dictionary<string, object> dic = new Dictionary<string, object>();dic.Add("x-expires", 30000);dic.Add("x-message-ttl", 12000);//队列上消息过期时间,应小于队列过期时间 dic.Add("x-dead-letter-exchange", "exchange-direct");//过期消息转向路由 dic.Add("x-dead-letter-routing-key", "routing-delay");//过期消息转向路由相匹配routingkey //创建一个名叫"zzhello"的消息队列channel.QueueDeclare(queue: "zzhello",durable: true,exclusive: false,autoDelete: false,arguments: dic); var message = "Hello World!"; var body = Encoding.UTF8.GetBytes(message); //向该消息队列发送消息messagechannel.BasicPublish(exchange: "",routingKey: "zzhello",basicProperties: null,body: body);Console.WriteLine(" [x] Sent {0}", message);}}}Console.ReadKey();
消费者代码如下:
var factory = new ConnectionFactory() { HostName = "127.0.01", UserName = "test", Password = "test" }; using (var connection = factory.CreateConnection()){ using (var channel = connection.CreateModel()){channel.ExchangeDeclare(exchange: "exchange-direct", type: "direct"); string name = channel.QueueDeclare().QueueName;channel.QueueBind(queue: name, exchange: "exchange-direct", routingKey: "routing-delay"); //回调,当consumer收到消息后会执行该函数var consumer = new EventingBasicConsumer(channel);consumer.Received += (model, ea) =>{ var body = ea.Body; var message = Encoding.UTF8.GetString(body);Console.WriteLine(ea.RoutingKey);Console.WriteLine(" [x] Received {0}", message);}; //Console.WriteLine("name:" + name); //消费队列"hello"中的消息 channel.BasicConsume(queue: name,autoAck: true,consumer: consumer);Console.WriteLine(" Press [enter] to exit.");Console.ReadLine();}}Console.ReadKey();
效果 :
在等待了12秒后消费者等到了消息。
这样我们就实现了延迟队列的功能了。
转载于:https://blog.51cto.com/kiujyhgt/1917303
C#实现rabbitmq 延迟队列功能相关推荐
- Delayed Message 插件实现 RabbitMQ 延迟队列
延迟队列是为了存放那些延迟执行的消息,待消息过期之后消费端从队列里拿出来执行. DLX + TTL 方式存在的时序问题 对于延迟队列不管是 AMQP 协议或者 RabbitMQ 本身是不支持的,之前有 ...
- RabbitMQ 延迟队列-对于入门来说可以快速上手
RabbitMQ 延迟队列-非常非常实用 RabbitMQ 延迟队列-非常非常实用 一.使用场景 二.消息延迟推送的实现 三.项目具体实现 RabbitMQ 延迟队列-非常非常实用 一.使用场景 ...
- RabbitMQ 延迟队列实现定时任务的正确姿势,你学会了么?
以下文章来源方志朋的博客,回复"666"获面试宝典 场景 开发中经常需要用到定时任务,对于商城来说,定时任务尤其多,比如优惠券定时过期.订单定时关闭.微信支付2小时未支付关闭订单等 ...
- rabbitmq 延迟队列_Delayed Message 插件实现 RabbitMQ 延迟队列
延迟队列是为了存放那些延迟执行的消息,待消息过期之后消费端从队列里拿出来执行. DLX + TTL 方式存在的时序问题 对于延迟队列不管是 AMQP 协议或者 RabbitMQ 本身是不支持的,之前有 ...
- 谷粒商城笔记+踩坑(22)——库存自动解锁。RabbitMQ延迟队列
导航: 谷粒商城笔记+踩坑汇总篇 目录 1 业务流程,订单失败后自动回滚解锁库存 可靠消息+最终一致性方案 2[仓库服务]RabbitMQ环境准备 2.1 导入依赖 2.2 yml配置RabbitMQ ...
- RabbitMQ 延迟队列,太实用了!
点击关注公众号,Java干货及时送达 目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如: 淘宝七天自动确认收货.在我们签收商品后,物流系统会在七天后延时发送一个消息给支付系统,通知支付 ...
- RabbitMQ(九):RabbitMQ 延迟队列,消息延迟推送(Spring boot 版)
应用场景 目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如: 淘宝七天自动确认收货.在我们签收商品后,物流系统会在七天后延时发送一个消息给支付系统,通知支付系统将款打给商家,这个过程持 ...
- rabbitmq 延迟队列_框架系列|中间件RabbitMQ必看17道面试题
46. RabbitMQ 的使用场景有哪些? 抢购活动,削峰填谷,防止系统崩塌. 延迟信息处理,比如 10 分钟之后给下单未付款的用户发送邮件提醒. 解耦系统,对于新增的功能可以单独写模块扩展,比如用 ...
- Spring Boot(十四)RabbitMQ延迟队列
一.前言 延迟队列的使用场景:1.未按时支付的订单,30分钟过期之后取消订单:2.给活跃度比较低的用户间隔N天之后推送消息,提高活跃度:3.过1分钟给新注册会员的用户,发送注册邮件等. 实现延迟队列的 ...
最新文章
- PAT甲级1050 String Subtraction:[C++题解]字符串作差
- win7怎么查看电脑配置_电脑死机是什么原因?出现问题你会怎么办?
- docker 搜寻 包 版本_ubuntu16.04下安装docker容器
- [树套树] 网络管理
- java ee13_一口气了解多线程及其Java实现
- curl在android服务器上编译,Android curl的上载编译和使用
- 简明 Vim 练级攻略 (转)
- 贴片晶振脚位_贴片晶振的焊接方法和注意事项
- linux 可以ping 通 windows ,windows ping 不了 linux
- gd公文文件转换成pdf格式
- HTML编辑器-HTML网页表单可视化在线编辑器插件大全
- 网上购物系统问题陈述、词汇表与领域类图
- 微信公众平台、微信开放平台、微信商户平台的区别
- 建筑施工企业工程项目成本管理软件
- 考试周来临。。蓦然回首
- GEE学习笔记(基础篇)更新中
- 地图标记(学习笔记)
- 数字人民币概论、特征、架构介绍
- delphi的connection closed Gracefully错误
- 诺顿360偷偷挖矿被怒喷 官方却说:都是为了用户好