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.点我达订单 ...
随机推荐
- 转发请求RequestDispatcher()方法用于与页面的交互
jsp1代码 <form action="HelloServlet" > 账号: <input type="text" name=" ...
- 认证授权:IdentityServer4 - 各种授权模式应用
前言: 前面介绍了IdentityServer4 的简单应用,本篇将继续讲解IdentityServer4 的各种授权模式使用示例 授权模式: 环境准备 a)调整项目结构如下: b)调整cz.Id ...
- 《搭建个人Leanote云笔记本》
体验实验室简介 阿里云开发者实验室,提供免费阿里云资源,丰富的云计算应用场景, Step by Step 完成云产品的体验 教程介绍 本教程将介绍如何搭建个人Leanote云笔记本. 场景体验 阿里云 ...
- Centos7,PHP7安装swoole
Swoole详细介绍及如何使用,这里暂时不做说明,可以参考一下文档:https://wiki.swoole.com/ 源码编译安装 下载地址如下: https://github.com/swoole/ ...
- git代码管理——克隆项目到本地仓库及上传本地项目到仓库
一.克隆项目到本地仓库 1.github网站操作 1.1 登录github 首先创建一个仓库,点击“New” 1.2 输入仓库信息 1.3 创建完成后,会多出一个仓库 2.安装git客户端 2.1 安 ...
- Combine 框架,从0到1 —— 4.在 Combine 中执行异步代码
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 4.在 Combine 中执行异步代码. 内容概览 前言 用 Future 取代回调闭包 用输出类型( ...
- Flutter中如何方便的获取音视频的长度
此次主要是flutter集成im,在发送视频时需要加上时长,但是用视频controller只能在初始化时具备路径才可以可以使用:just_audio插件中的方法进行获取 详情看官方文档:https:/ ...
- 谈谈Netty内存管理
前言 正是Netty的易用性和高性能成就了Netty,让其能够如此流行. 而作为一款通信框架,首当其冲的便是对IO性能的高要求. 不少读者都知道Netty底层通过使用Direct Memory,减少了 ...
- python的快捷键
常用快捷键 1.Ctrl + Enter:在下方新建行但不移动光标 2.Shift + Enter:在下方新建行并移到新行行首 3.Ctrl + /:注释(取消注释)选择的行 4.Ctrl + Alt ...
- vscode写latex的正反向搜索问题
vscode写latex的正反向搜索问题 vscode使用LaTeX Workshop + TexLive时可以很舒畅的写作 但是在长篇写作时,会涉及到正反向搜索的需求.即根据源码搜pdf的位置,和根 ...