PHP怎样写延时队列(定时器)
背景
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怎样写延时队列(定时器)的更多相关文章
- rabbitmq 延时队列
前言 某个产品 或者订单,有个有效期 过了有效期要取消 方法一 : 写个脚本,用crontab 定时扫描 改变状态 但是最低只能一分钟 ,不适合 方法二 : 用swoole得毫秒定时器,每秒钟去扫描表 ...
- Kafka 延时队列&重试队列
一.延时队列 1. 简介 TimingWheel是kafka时间轮的实现,内部包含了⼀个TimerTaskList数组,每个数组包含了⼀些链表组成的TimerTaskEntry事件,每个TimerTa ...
- 简析LIVE555中的延时队列
http://www.cnblogs.com/nightwatcher/archive/2011/04/10/2011158.html 最近在看LIVE555的源码,感觉其中的延时队列写的不错,于是就 ...
- RabbitMQ进阶使用-延时队列的配置(Spring Boot)
依赖 MAVEN配置pom.xml <dependency> <groupId>org.springframework.boot</groupId> <art ...
- 手写阻塞队列(Condition实现)
自己实现阻塞队列的话可以采用Object下的wait和notify方法,也可以使用Lock锁提供的Condition来实现,本文就是自己手撸的一个简单的阻塞队列,部分借鉴了JDK的源码.Ps:最近看面 ...
- 基于rabbitMQ 消息延时队列方案 模拟电商超时未支付订单处理场景
前言 传统处理超时订单 采取定时任务轮训数据库订单,并且批量处理.其弊端也是显而易见的:对服务器.数据库性会有很大的要求,并且当处理大量订单起来会很力不从心,而且实时性也不是特别好 当然传统的手法还可 ...
- 微服务-springboot-rabbitmq:实现延时队列
延时队列应用于什么场景 延时队列顾名思义,即放置在该队列里面的消息是不需要立即消费的,而是等待一段时间之后取出消费.那么,为什么需要延迟消费呢?我们来看以下的场景 网上商城下订单后30分钟后没有完成支 ...
- java延时队列
应用场景 1)7天自动收货 a.用户支付完成以后,把订单ID插入到内存的一个DelayQueue中,同时插入到Redis中. b.7天之内,用户点击了确认收货,则从DelayQueue中删除,从Red ...
- Redis学习笔记02-消息队列与延时队列
写在前面:Redis的消息队列并不是专业的消息队列,没有ACK保证,没有特别多的高级特性,如果对消息的可靠性有很高的要求,就放弃它吧. 1.Redis消息队列 Redis通过内部的list数据结构来实 ...
随机推荐
- Java基础系列(5)- 使用IDEA开发
IDEA开发 下载安装IDEA https://www.cnblogs.com/gltou/p/14956060.html 使用IDEA编写helloworld 踩坑总结 run的时候提示" ...
- JDBC-3(Transcation) ****
3.1 异常的使用说明 在工具类中(JDBCUtils)的方法最好声明异常(throws),以便后续实现类中去捕获这些异常. 工具类中捕获异常通常没有意义 eg:实现类中connection建立过程出 ...
- [源码解析] PyTorch 流水线并行实现 (3)--切分数据和运行时系统
[源码解析] PyTorch 流水线并行实现 (3)--切分数据和运行时系统 目录 [源码解析] PyTorch 流水线并行实现 (3)--切分数据和运行时系统 0x00 摘要 0x01 分割小批次 ...
- YbtOJ#463-序列划分【二分答案,线段树,dp】
正题 题目链接:https://www.ybtoj.com.cn/problem/463 题目大意 给出长度为\(n\)的序列\(A,B\).要求划分成若干段满足 对于任何\(i<j\),若\( ...
- P4345-[SHOI2015]超能粒子炮·改【Lucas定理,类欧】
正题 题目链接:https://www.luogu.com.cn/problem/P4345 题目大意 \(T\)组询问,给出\(n,k\)求 \[\sum_{i=0}^{k}\binom{n}{i} ...
- 双击tomcat8w.exe出现指定的服务未安装
进入tomcat bin 目录下 打开cmd 输入命令 service.bat install 进行服务安装. 双击tomcat8w.exe 就可以打开了.
- 自从学会了Python自动化Pytest框架,领导再也不敢在我背后指手划脚了
前言 大家都知道Python有自带的单元测试框架unittest,那为什么还要学习Pytest呢?先了解下Pytest优点 pytest: pytest是一个非常成熟的全功能的Python测试框架,是 ...
- 从0到1使用Kubernetes系列(三):使用Ansible安装Kubernetes集群
前两期的文章介绍了Kubernetes基本概念和架构,用Kubeadm+Ansible搭建Kubernetes集群所需要的工具及其作用.本篇介绍怎么使用Ansible安装Kubernetes集群. 启 ...
- [源码解析]PyTorch如何实现前向传播(1) --- 基础类(上)
[源码解析]PyTorch如何实现前向传播(1) --- 基础类(上) 目录 [源码解析]PyTorch如何实现前向传播(1) --- 基础类(上) 0x00 摘要 0x01 总体逻辑 0x02 废弃 ...
- Python - faker
安装 faker pip install Faker pip install Dumper 设置生成器 from faker import Faker fake = Faker() 它可以通过访问以想 ...