rabbitmq 延时队列
前言
某个产品 或者订单,有个有效期 过了有效期要取消
方法一 : 写个脚本,用crontab 定时扫描 改变状态 但是最低只能一分钟 ,不适合
方法二 : 用swoole得毫秒定时器,每秒钟去扫描表 明显占用资源 mysql受不了
方法三 :用rabbitmq延时队列 一开始将其丢入mq 死信队列,设置有效期,过时转发到其他队列,再启动一个消费者 消费 更改表状态
php 安装mq扩展
https://www.cnblogs.com/brady-wang/p/7662393.html
搭建mq服务
https://www.cnblogs.com/brady-wang/p/7660174.html
创建生产者和消费者
生产者 publish.php
<?php
header('Content-Type:text/html;charset=utf8;');
$time = 30;
$params = array(
'exchangeName' => 'test_cache_exchange'."_".$time,
'queueName' => 'test_cache_queue'."_".$time,
'routeKey' => 'test_cache_route'."_".$time,
);
$connectConfig = array(
'host' => '127.0.0.1',
'port' => 5672,
'login' => 'admin',
'password' => 'password',
'vhost' => '/'
);
//var_dump(extension_loaded('amqp'));
//
//exit();
try {
$conn = new AMQPConnection($connectConfig);
$conn->connect();
if (!$conn->isConnected()) {
//die('Conexiune esuata');
//TODO 记录日志
echo 'rabbit-mq 连接错误:', json_encode($connectConfig);
exit();
}
$channel = new AMQPChannel($conn);
if (!$channel->isConnected()) {
// die('Connection through channel failed');
//TODO 记录日志
echo 'rabbit-mq Connection through channel failed:', json_encode($connectConfig);
exit();
}
$exchange = new AMQPExchange($channel);
$exchange->setFlags(AMQP_DURABLE);//持久化
$exchange->setName($params['exchangeName']?:'');
$exchange->setType(AMQP_EX_TYPE_DIRECT); //direct类型
$exchange->declareExchange();
//$channel->startTransaction();
$queue = new AMQPQueue($channel);
$queue->setName($params['queueName']?:'');
$queue->setFlags(AMQP_DURABLE);
// 和普通生产者区别 在这 下面是过期时间和转发到的路由
$queue->setArguments(array(
'x-dead-letter-exchange' => 'delay_exchange',
'x-dead-letter-routing-key' => 'delay_route',
'x-message-ttl' => $time*1000,
));
$queue->declareQueue();
//绑定
$queue->bind($params['exchangeName'], $params['routeKey']);
} catch(Exception $e) {
}
//$num = mt_rand(100, 500);
$num = 1;
//生成消息
$exchange->publish(date("Y-m-d H:i:s"), $params['routeKey'], AMQP_MANDATORY, array('delivery_mode'=>2));
消费者 consumer.php
<?php
header('Content-Type:text/html;charset=utf8;');
$params = array(
'exchangeName' => 'delay_exchange',
'queueName' => 'delay_queue',
'routeKey' => 'delay_route',
);
$connectConfig = array(
'host' => 'localhost',
'port' => 5672,
'login' => 'admin',
'password' => 'password',
'vhost' => '/'
);
//var_dump(extension_loaded('amqp'));
//exit();
try {
$conn = new AMQPConnection($connectConfig);
$conn->connect();
if (!$conn->isConnected()) {
//die('Conexiuneesuata');
//TODO记录日志
echo 'rabbit-mq连接错误:', json_encode($connectConfig);
exit();
}
$channel = new AMQPChannel($conn);
if (!$channel->isConnected()) {
//die('Connectionthroughchannelfailed');
//TODO记录日志
echo 'rabbit-mqConnectionthroughchannelfailed:', json_encode($connectConfig);
exit();
}
$exchange = new AMQPExchange($channel);
$exchange->setFlags(AMQP_DURABLE);//声明一个已存在的交换器的,如果不存在将抛出异常,这个一般用在consume端
$exchange->setName($params['exchangeName'] ?: '');
$exchange->setType(AMQP_EX_TYPE_DIRECT);//direct类型
$exchange->declareExchange();
//$channel->startTransaction();
$queue = new AMQPQueue($channel);
$queue->setName($params['queueName'] ?: '');
$queue->setFlags(AMQP_DURABLE);
$queue->declareQueue();
//绑定
$queue->bind($params['exchangeName'], $params['routeKey']);
} catch (Exception$e) {
echo $e->getMessage();
exit();
}
function callback(AMQPEnvelope $message){
global $queue;
if ($message) {
$body = $message->getBody();
echo $body . PHP_EOL;
$queue->ack($message->getDeliveryTag());
} else {
echo 'nomessage' . PHP_EOL;
}
}
//$queue->consume('callback');第一种消费方式,但是会阻塞,程序一直会卡在此处
//第二种消费方式,非阻塞
$start = time();
while (true) {
$message = $queue->get();
if (!empty($message)) {
echo $message->getBody()."--失效时间 ".date("Y-m-d H:i:s"). PHP_EOL;
$queue->ack($message->getDeliveryTag());//应答,代表该消息已经消费
// $end = time();
// echo '<br>' . ($end - $start);
} else {
//echo'messagenotfound'.PHP_EOL;
}
}
执行推送 我改了不同时间推送,会生成不同的交换机 路由 队列,因为我用得是direct类型 要一一匹配

消费者开启
[root@localhost mq]# php consumer.php
2020-07-18 11:07:22--失效时间 2020-07-18 11:07:42
2020-07-18 11:07:22--失效时间 2020-07-18 11:07:42
2020-07-18 11:07:23--失效时间 2020-07-18 11:07:43
2020-07-18 11:07:23--失效时间 2020-07-18 11:07:43
2020-07-18 11:13:04--失效时间 2020-07-18 11:13:24 2020-07-18 11:21:00--失效时间 2020-07-18 11:21:10
2020-07-18 11:21:32--失效时间 2020-07-18 11:22:02
2020-07-18 11:21:32--失效时间 2020-07-18 11:22:02
2020-07-18 11:21:22--失效时间 2020-07-18 11:22:12
2020-07-18 11:21:23--失效时间 2020-07-18 11:22:13
2020-07-18 11:21:23--失效时间 2020-07-18 11:22:13
发现正常,都是我设置的事件过期后就到处理队列,在这里消费,处理逻辑即可
参考 https://www.cnblogs.com/Zhangcsc/p/11739754.html
https://blog.csdn.net/weixin_34310369/article/details/92262465?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-2
rabbitmq 延时队列的更多相关文章
- java实现rabbitMQ延时队列详解以及spring-rabbit整合教程
在实际的业务中我们会遇见生产者产生的消息,不立即消费,而是延时一段时间在消费.RabbitMQ本身没有直接支持延迟队列功能,但是我们可以根据其特性Per-Queue Message TTL和 Dead ...
- IOS IAP 自动续订 之 利用rabbitmq延时队列自动轮询检查是否续订成功
启用针对自动续期订阅的服务器通知: - 官方地址: - https://help.apple.com/app-store-connect/#/dev0067a330b - 相关字段, 相关类型地址: ...
- RabbitMQ延时队列应用场景
应用场景 我们系统未付款的订单,超过一定时间后,需要系统自动取消订单并释放占有物品 常用的方案 就是利用Spring schedule定时任务,轮询检查数据库 但是会消耗系统内存,增加了数据库的压力. ...
- rabbitmq 延时队列 插件方式实现 每条消息都延时自己时间
上篇文章的延时是加到队列上的 通过死信过时推送 ,缺点就是不能每条消息定义自己的过时时间而且每次有新的过时时间,要新建一个交换机和队列 https://www.cnblogs.com/brady-wa ...
- RabbitMQ 延时消息队列
消息延时在日常随处可见: 1.订单创建10min之后不发起支付,自动取消. 2.30min定时推送一次邮件信息. 最常用到方式后台定时任务轮训,量小的时候可以使用,量大会出现数据读取会性能问题.Rab ...
- 基于rabbitMQ 消息延时队列方案 模拟电商超时未支付订单处理场景
前言 传统处理超时订单 采取定时任务轮训数据库订单,并且批量处理.其弊端也是显而易见的:对服务器.数据库性会有很大的要求,并且当处理大量订单起来会很力不从心,而且实时性也不是特别好 当然传统的手法还可 ...
- 面试官:RabbitMQ过期时间设置、死信队列、延时队列怎么设计?
哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 RabbitMQ我们经常的使用, ...
- 基于Redis实现延时队列服务
背景 在业务发展过程中,会出现一些需要延时处理的场景,比如: a.订单下单之后超过30分钟用户未支付,需要取消订单 b.订单一些评论,如果48h用户未对商家评论,系统会自动产生一条默认评论 c.点我达 ...
- 【转】基于Redis实现延时队列服务
背景 在业务发展过程中,会出现一些需要延时处理的场景,比如: a.订单下单之后超过30分钟用户未支付,需要取消订单b.订单一些评论,如果48h用户未对商家评论,系统会自动产生一条默认评论c.点我达订单 ...
随机推荐
- JS语法_类型
类型 JS 的数据类型 boolean number string undefined null symbol object TS 额外的数据类型 void BigInt 是一种内置对象,它提供了一种 ...
- 【NOIP2013模拟】黑魔法师之门
题目描述 经过了16个工作日的紧张忙碌,未来的人类终于收集到了足够的能源.然而在与Violet星球的战争中,由于Z副官的愚蠢,地球的领袖applepi被邪恶的黑魔法师Vani囚禁在了Violet星球. ...
- HotSpot VM执行引擎的实现
Java代码的执行分类: 第一种是将源代码编译成字节码文件,然后再运行时通过解释器将字节码文件转为机器码执行 第二种是编译执行(直接编译成机器码).现代虚拟机为了提高执行效率,会使用即时编译技术(JI ...
- JVM学习(七)JMM内存模型
一.什么是JMM 概念:Java内存模型(Java Memory Model ,JMM)就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能 ...
- lua、python对比学习
一.基本数据类型: lua: nil(空).boolean(false和nil为假).number(数值).string(字符串).table(表).function(方法).thread (线程) ...
- 论文阅读笔记: Natural Language Inference over Interaction Space
这篇文章提出了DIIN(DENSELY INTERACTIVE INFERENCE NETWORK)模型. 是解决NLI(NATURAL LANGUAGE INFERENCE)问题的很好的一种方法. ...
- 微服务实战系列(七)-网关springcloud gateway
1. 场景描述 springcloud刚推出的时候用的是netflix全家桶,路由用的zuul,但是据说zull1.0在大数据量访问的时候存在较大性能问题,2.0就没集成到springcloud中了, ...
- Windows无法安装到GPT格式磁盘的根本解决办法 - 初学者系列 - 学习者系列文章
上次在MSDN系统QQ群里有朋友问到在安装操作系统的时候有个问题:Windows无法安装到GPT格式磁盘,见图: 我在这里说下,使用网上方法的都是小白,就是说网上那些都是小白.下面介绍如何正确安装操作 ...
- springmvc 源码分析(一)-- DisparcherServlet的创建和注册到tomcat
一. servlet 3.0 的使用 1.1 环境搭建: servlet跟spring没有任何关系,我创建一个servlet可以不依赖spring,现在搭建一个纯的servlet项目,并实现简单的类似 ...
- 关于Xilinx PCIE DMA的问答
关于Xilinx PCIE DMA的问答 很久没上博客园了,但由于之前在博客园写了几篇关于PCIE DMA的文章,很多同学给我发消息询问相关知识点,之前有空的时候都是语音一小时跟人细讲,最近由于工作繁 ...