最近在研究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 延迟队列功能相关推荐

  1. Delayed Message 插件实现 RabbitMQ 延迟队列

    延迟队列是为了存放那些延迟执行的消息,待消息过期之后消费端从队列里拿出来执行. DLX + TTL 方式存在的时序问题 对于延迟队列不管是 AMQP 协议或者 RabbitMQ 本身是不支持的,之前有 ...

  2. RabbitMQ 延迟队列-对于入门来说可以快速上手

    RabbitMQ 延迟队列-非常非常实用 RabbitMQ 延迟队列-非常非常实用 一.使用场景 二.消息延迟推送的实现 三.项目具体实现 RabbitMQ 延迟队列-非常非常实用 一.使用场景 ​ ...

  3. RabbitMQ 延迟队列实现定时任务的正确姿势,你学会了么?

    以下文章来源方志朋的博客,回复"666"获面试宝典 场景 开发中经常需要用到定时任务,对于商城来说,定时任务尤其多,比如优惠券定时过期.订单定时关闭.微信支付2小时未支付关闭订单等 ...

  4. rabbitmq 延迟队列_Delayed Message 插件实现 RabbitMQ 延迟队列

    延迟队列是为了存放那些延迟执行的消息,待消息过期之后消费端从队列里拿出来执行. DLX + TTL 方式存在的时序问题 对于延迟队列不管是 AMQP 协议或者 RabbitMQ 本身是不支持的,之前有 ...

  5. 谷粒商城笔记+踩坑(22)——库存自动解锁。RabbitMQ延迟队列

    导航: 谷粒商城笔记+踩坑汇总篇 目录 1 业务流程,订单失败后自动回滚解锁库存 可靠消息+最终一致性方案 2[仓库服务]RabbitMQ环境准备 2.1 导入依赖 2.2 yml配置RabbitMQ ...

  6. RabbitMQ 延迟队列,太实用了!

    点击关注公众号,Java干货及时送达 目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如: 淘宝七天自动确认收货.在我们签收商品后,物流系统会在七天后延时发送一个消息给支付系统,通知支付 ...

  7. RabbitMQ(九):RabbitMQ 延迟队列,消息延迟推送(Spring boot 版)

    应用场景 目前常见的应用软件都有消息的延迟推送的影子,应用也极为广泛,例如: 淘宝七天自动确认收货.在我们签收商品后,物流系统会在七天后延时发送一个消息给支付系统,通知支付系统将款打给商家,这个过程持 ...

  8. rabbitmq 延迟队列_框架系列|中间件RabbitMQ必看17道面试题

    46. RabbitMQ 的使用场景有哪些? 抢购活动,削峰填谷,防止系统崩塌. 延迟信息处理,比如 10 分钟之后给下单未付款的用户发送邮件提醒. 解耦系统,对于新增的功能可以单独写模块扩展,比如用 ...

  9. Spring Boot(十四)RabbitMQ延迟队列

    一.前言 延迟队列的使用场景:1.未按时支付的订单,30分钟过期之后取消订单:2.给活跃度比较低的用户间隔N天之后推送消息,提高活跃度:3.过1分钟给新注册会员的用户,发送注册邮件等. 实现延迟队列的 ...

最新文章

  1. PAT甲级1050 String Subtraction:[C++题解]字符串作差
  2. win7怎么查看电脑配置_电脑死机是什么原因?出现问题你会怎么办?
  3. docker 搜寻 包 版本_ubuntu16.04下安装docker容器
  4. [树套树] 网络管理
  5. java ee13_一口气了解多线程及其Java实现
  6. curl在android服务器上编译,Android curl的上载编译和使用
  7. 简明 Vim 练级攻略 (转)
  8. 贴片晶振脚位_贴片晶振的焊接方法和注意事项
  9. linux 可以ping 通 windows ,windows ping 不了 linux
  10. gd公文文件转换成pdf格式
  11. HTML编辑器-HTML网页表单可视化在线编辑器插件大全
  12. 网上购物系统问题陈述、词汇表与领域类图
  13. 微信公众平台、微信开放平台、微信商户平台的区别
  14. 建筑施工企业工程项目成本管理软件
  15. 考试周来临。。蓦然回首
  16. GEE学习笔记(基础篇)更新中
  17. 地图标记(学习笔记)
  18. 数字人民币概论、特征、架构介绍
  19. delphi的connection closed Gracefully错误
  20. 诺顿360偷偷挖矿被怒喷 官方却说:都是为了用户好

热门文章

  1. 初学者 | 一文读懂命名实体识别
  2. 王维嘉:神经网络的本质是在数据里面提取相关性
  3. 目前最实用的机器学习算法,你认为是哪几种?
  4. 干货丨不确定性原理——人工智能的哲学基础
  5. 互联互通下的超级App价值重构
  6. CCF发布2020-2021中国计算机科学技术发展报告
  7. 寒武纪上市:AI芯片和普通芯片有何不同?全球AI芯片公司大全都在这里了
  8. 新基建的内涵、意义和隐忧 ,基于互联网大脑模型的分析
  9. Google AI 研发医疗新模型,预测死亡率比医院高出10%
  10. Gartner预测:2025年,人工智能将创造200万个新增就业机会