本文目录一览:
php使用redis的有序集合zset实现延迟队列
延迟队列就是个带延迟功能的消息队列,相对于普通队列,它可以在指定时间消费掉消息。
我们通过redis的有序集合zset来实现简单的延迟队列,将消息数据序列化,作为zset的value,把消息处理时间作为score,每次通过zRangeByScore获取一条消息进行处理。
然后,我们写一个php脚本,用来处理队列中的任务。
TP6队列think-queue(延时队列/自动取消订单/php自动操作)
什么是延时队列?顾名思义:首先它要具有队列的特性,再给它附加一个延迟消费队列消息的功能,也就是说可以指定队列中的消息在哪个时间点被消费。
延时队列在项目中的应用还是比较多的,尤其像电商类平台订单成功后,在30分钟内没有支付,自动取消订单
外卖平台发送订餐通知,下单成功后60s给用户推送短信。
如果订单一直处于某一个未完结状态时,及时处理关单,并退还库存
淘宝新建商户一个月内还没上传商品信息,将冻结商铺等
……
上边的这些场景都可以应用延时队列解决。
1.安装think-queue
2.安装redis
3.配置,项目\config\queue.php
4.创建队列和推送
新增 \app\job\test.php 控制器,在该控制器中添加 fire 方法
fire方法是消息队列默认调用的方法
5.在项目中进行调用延时队列方法
6.添加监听 - 重要必要有这个监听,Queue::later才有效
Redis使用zset有序集合做延迟队列
把所有需要在未来执行的任务都添加到有序集合里面,并将任务的执行时间设置为分值,另外再使用一个进程来查找有序集合里面是否存在可以立即执行的任务,如果有的话,就从有序集合里面移除那个任务,并将它添加到适当的任务队列里面。
--出自《Redis实战》
创建函数 addFutureJob,负责将延迟任务添加到有序集合job中。
有序集合里存储的元素,可以使用json格式保存。
内部结构可以类似如下这种:
参数:
$job: 存储延迟任务的有序集合的名字,叫job
$queue: 当任务到达执行时间时,转存到具体的队列里执行
$fun: 负责执行的函数名称或匿名函数
$time: 延迟任务执行的具体时间
$parameter: 传递的参数
执行脚本后,将存储到job 这个有序集合里
另一个脚本中,读取job集合,检查是否有需要执行的任务
这个函数getQueue()的基本流程是这样:
(1)根据分数从小到大排列,读取第一个元素。如果元素不存在返回false
(2) 如果元素任务存在,并且它的分数(执行时间)小于等于当前时间,说明这个任务可以执行了。
(3) json转化成数组,读取任务的queue参数,将它添加到指定的队列里,然后从job中删除这个任务。
(4) 上述转移操作时,如果成功,记录日志。while继续循环检查job有序集合
(5) 如果转移操作失败,返回false
(6) 后续没有要执行的任务时,停止循环,返回false
此处循环读取也可以使用zrangeByScore()函数,根据分数范围进行读取返回集合内的指定元素。