前言

某个产品 或者订单,有个有效期 过了有效期要取消

方法一 : 写个脚本,用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 延时队列的更多相关文章

  1. java实现rabbitMQ延时队列详解以及spring-rabbit整合教程

    在实际的业务中我们会遇见生产者产生的消息,不立即消费,而是延时一段时间在消费.RabbitMQ本身没有直接支持延迟队列功能,但是我们可以根据其特性Per-Queue Message TTL和 Dead ...

  2. IOS IAP 自动续订 之 利用rabbitmq延时队列自动轮询检查是否续订成功

    启用针对自动续期订阅的服务器通知: - 官方地址: - https://help.apple.com/app-store-connect/#/dev0067a330b - 相关字段, 相关类型地址:  ...

  3. RabbitMQ延时队列应用场景

    应用场景 我们系统未付款的订单,超过一定时间后,需要系统自动取消订单并释放占有物品 常用的方案 就是利用Spring schedule定时任务,轮询检查数据库 但是会消耗系统内存,增加了数据库的压力. ...

  4. rabbitmq 延时队列 插件方式实现 每条消息都延时自己时间

    上篇文章的延时是加到队列上的 通过死信过时推送 ,缺点就是不能每条消息定义自己的过时时间而且每次有新的过时时间,要新建一个交换机和队列 https://www.cnblogs.com/brady-wa ...

  5. RabbitMQ 延时消息队列

    消息延时在日常随处可见: 1.订单创建10min之后不发起支付,自动取消. 2.30min定时推送一次邮件信息. 最常用到方式后台定时任务轮训,量小的时候可以使用,量大会出现数据读取会性能问题.Rab ...

  6. 基于rabbitMQ 消息延时队列方案 模拟电商超时未支付订单处理场景

    前言 传统处理超时订单 采取定时任务轮训数据库订单,并且批量处理.其弊端也是显而易见的:对服务器.数据库性会有很大的要求,并且当处理大量订单起来会很力不从心,而且实时性也不是特别好 当然传统的手法还可 ...

  7. 面试官:RabbitMQ过期时间设置、死信队列、延时队列怎么设计?

    哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 RabbitMQ我们经常的使用, ...

  8. 基于Redis实现延时队列服务

    背景 在业务发展过程中,会出现一些需要延时处理的场景,比如: a.订单下单之后超过30分钟用户未支付,需要取消订单 b.订单一些评论,如果48h用户未对商家评论,系统会自动产生一条默认评论 c.点我达 ...

  9. 【转】基于Redis实现延时队列服务

    背景 在业务发展过程中,会出现一些需要延时处理的场景,比如: a.订单下单之后超过30分钟用户未支付,需要取消订单b.订单一些评论,如果48h用户未对商家评论,系统会自动产生一条默认评论c.点我达订单 ...

随机推荐

  1. 调整JavaScript抽象的迭代方案

    原文链接:Adapting JavaScript Abstractions Over Time 译者:小溪里 校对者:郭华翔.苗冬青 即使还没有读过我的文章<在处理网络数据的 JavaScrip ...

  2. warning: #1295-D: Deprecated declaration LED_Init - give arg types警告的解决办法

  3. An Introduction to Differential Privacy

    原文链接:An Introduction to Differential Privacy 差分隐私算法可以允许分析人员执行良性的聚合分析,同时保证个人隐私得到切实的保护.. 背景数据分析中的隐私保护技 ...

  4. Node.js连接MongoDB数据库

    首先要启动MongoDB服务器 先找到你的mongoDb安装目录,我的如下:就在bin文件夹下创建一个data文件夹,data内包含两个空文件夹,如下: 接着回到bin文件夹处,按住shift键,右击 ...

  5. [05] 通过P/Invoke加速C#程序

    通过P/Invoke加速C#程序 任何语言都会提供FFI机制(Foreign Function Interface, 叫法不太一样), 大多数的FFI机制是和C API. C#提供了P/Invoke来 ...

  6. linux 多进程

    Linux下的多进程编程初步 Linux下的多进程编程初步 多进程编程 1 Linux下进程的结构 2 Linux下的进程控制 21 僵尸进程 22 fork 23 exec 函数族 3 Linux下 ...

  7. 深入分析Linux内核链表

    1. 普通单链表 2. 内核链表 上图是本人从其他博客盗来的,差点被糊弄过去. 下图是本人自己用KeyNote画的(唉!!画图真的是让人心好累啊!!). 差异是不是很明显啊?! Read The Fu ...

  8. 摆书 book

    题目描述: dxy家收藏了一套书,这套书叫<SDOI故事集>,<SDOI故事集>有n(n≤19)本,每本书有一个编号,从1号到n号. dxy把这些书按编号从小到大,从上往下摞成 ...

  9. [记录点滴]授人以渔,从Tensorflow找不到dll扩展到如何排查问题

    [记录点滴]授人以渔,从Tensorflow找不到dll扩展到如何排查问题 目录 [记录点滴]授人以渔,从Tensorflow找不到dll扩展到如何排查问题 0x00 摘要 0x01 引言 0x02 ...

  10. 第 8 篇:内容支持 Markdown 语法,接口返回包含解析后的 HTML

    作者:HelloGitHub-追梦人物 在 Django博客教程(第二版) 中,我们给博客内容增加了 Markdown 的支持,博客详情接口应该返回解析后的 HTML 内容. 来回顾一下 Post 模 ...