背景

PHP没有定时器,依托的都是crontab这样的系统工具,也没有go中defer这样的延时方法,本文介绍几种PHP写延时队列的几种姿势。

延时队列的定义

普通的队列是先进先出,但是延时队列并不是,而是加上了时间这一权重。希望到达时间点的先执行。

从某种意义上来讲,延迟队列的结构并不像一个队列,而更像是一种以时间为权重的有序堆结构。

Hash

将key使用一个唯一标识,保证每个任务都不重复,也方便删除,然后value中添加需要调用的函数名和时间戳,以及参数。

没秒进行遍历,然后将时间到的取出来执行,再删除。

入队:hSet key:uuid value:{timestamp,function,param}

出队:timestamp > now do function(param)

问题很明显,需要遍历,hGetAll是禁忌法术。

ZSet

前面谈到了,其实延时队列就是一种有序堆结构,就是需要加上一个时间权重,那么,有序集合不就是这样的么?

入队:ZADD KEY timestamp task ,我们将需要处理的任务,按其需要延迟处理时间作为 Score 加入到 ZSet 中。

出队:ZRANGEBYSCORE KEY -inf +inf limit 0 1 WITHSCORES。这样就能取出需要执行的任务了。执行完后删除:Zremrangebyscore KEY -inf +inf limit

时间轮

其实以上的算法,都有个小问题,同一时间线的任务先后问题,比如都是凌晨00执行的,怎么谁先谁后?因为任务是有优先级或者顺序的,当然也可以按优先级设置多个key,思路有很多。

这里在介绍一种算法,也是很多消息队列软件使用的,时间轮算法。

其实也很简单,就是每个时间点放一个队列,然后用一个任务去扫描时间轮,就像时钟一样,这样就能到点执行对应的任务了。

比如任务扫描到了2,需要添加一个延时3秒的任务,就直接添加到5上面。

当然对于时间粒度不同,我们肯定要设置多个时间轮,就像时针分针秒针。

这样的好处是什么?

  • 前面两种方式,说到底,需要遍历+排序,而时间轮,只需要逐步扫描逐步取出任务就好了。效率上高了很多,任务越多越明显。

PHP怎样写延时队列(定时器)的更多相关文章

  1. rabbitmq 延时队列

    前言 某个产品 或者订单,有个有效期 过了有效期要取消 方法一 : 写个脚本,用crontab 定时扫描 改变状态 但是最低只能一分钟 ,不适合 方法二 : 用swoole得毫秒定时器,每秒钟去扫描表 ...

  2. Kafka 延时队列&重试队列

    一.延时队列 1. 简介 TimingWheel是kafka时间轮的实现,内部包含了⼀个TimerTaskList数组,每个数组包含了⼀些链表组成的TimerTaskEntry事件,每个TimerTa ...

  3. 简析LIVE555中的延时队列

    http://www.cnblogs.com/nightwatcher/archive/2011/04/10/2011158.html 最近在看LIVE555的源码,感觉其中的延时队列写的不错,于是就 ...

  4. RabbitMQ进阶使用-延时队列的配置(Spring Boot)

    依赖 MAVEN配置pom.xml <dependency> <groupId>org.springframework.boot</groupId> <art ...

  5. 手写阻塞队列(Condition实现)

    自己实现阻塞队列的话可以采用Object下的wait和notify方法,也可以使用Lock锁提供的Condition来实现,本文就是自己手撸的一个简单的阻塞队列,部分借鉴了JDK的源码.Ps:最近看面 ...

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

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

  7. 微服务-springboot-rabbitmq:实现延时队列

    延时队列应用于什么场景 延时队列顾名思义,即放置在该队列里面的消息是不需要立即消费的,而是等待一段时间之后取出消费.那么,为什么需要延迟消费呢?我们来看以下的场景 网上商城下订单后30分钟后没有完成支 ...

  8. java延时队列

    应用场景 1)7天自动收货 a.用户支付完成以后,把订单ID插入到内存的一个DelayQueue中,同时插入到Redis中. b.7天之内,用户点击了确认收货,则从DelayQueue中删除,从Red ...

  9. Redis学习笔记02-消息队列与延时队列

    写在前面:Redis的消息队列并不是专业的消息队列,没有ACK保证,没有特别多的高级特性,如果对消息的可靠性有很高的要求,就放弃它吧. 1.Redis消息队列 Redis通过内部的list数据结构来实 ...

随机推荐

  1. ecshop 首页调用指定分类下的销售排行

    /*首页调用指定分类下的销售排行*/ function get_cats_top10($cat = '') { $sql = 'SELECT cat_id, cat_name ' . 'FROM ' ...

  2. Jmeter系列(19)- 常用配置文件

    JMeter.properties :跟Jmeter配置相关的配置信息都在这边,比如:Jmeter GUI页面的语言.日志级别设置等 User.properties:用户自定义相关的所有变量,会复写J ...

  3. 安装VM-TOOLS,解压tar包时提示目录磁盘空间不足

    在虚拟机里安装了ubuntu-18.04.4-desktop-amd64,安装VM-TOOLS,解压tar包时提示目录磁盘空间不足. 解决方法一: 打开terminal,输入:sudo apt ins ...

  4. jmeter监控linux服务器资源

    https://blog.csdn.net/weixin_38102592/article/details/100136375 https://blog.csdn.net/liuqiuxiu/arti ...

  5. CF786C-Till I Collapse【树状数组倍增,优先队列】

    正题 题目链接:https://www.luogu.com.cn/problem/CF786C 题目大意 给出一个长度为\(n\)的序列. 对于每个\(k\in[1,n]\)求将\(n\)分成最少的段 ...

  6. 1.JDBC编程六步走以及实现案例

    1.注册驱动:通知Java程序我们要连接的是哪个品牌的数据库 2.获取数据库连接:Java进程和Mysql进程之间的通道开启了 3.获取数据库操作对象:这个对象是用来执行sql语句的 4.执行SQL语 ...

  7. PowerDotNet平台化软件架构设计与实现系列(02):数据库管理平台

    为了DB复用和简化管理,我们对常见应用依赖的DB模块进行更高级的提取和抽象. 虽然一些ORM可以简化DB开发,但是我们还是需要进行改进和优化,否则应用越多,后期管理运维越混乱. 根据常见开发需要,数据 ...

  8. Linux Bash命令杂记(cut sort uniq wc tee)

    Linux Bash命令杂记(cut sort uniq wc tee) 数据流重定向 标准输入(stdin):代码为0,使用<或<<: 标准输出(stdout):代码为1,使用&g ...

  9. 题解 「SCOI2016」萌萌哒

    link Description 一个长度为 $ n $ 的大数,用 $ S_1S_2S_3 \ldots S_n $表示,其中 $ S_i $ 表示数的第 $ i $ 位,$ S_1 $ 是数的最高 ...

  10. Java(7)流程控制语句中的for、while、do while循环

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201543.html 博客主页:https://www.cnblogs.com/testero ...