前言
因为需要做一个商品倒计时30min后取消,所以就考虑了延迟队列,
延迟队列字面意思,就是推迟执行某些任务。
内容
我分为两个php文件,一个进行添加,一个进行处理
- 生成数据
<?php
/**
* redis 延迟队列 添加数据
*/
try {
$redis = new redis(); //生成redis对象
$redis->connect('127.0.0.1',6379);//连接redis 默认端口6379
$redis->ping();//查询是否连接上,链接不上抛出异常。
$redis->zAdd('delay_queue',time()+20,json_encode(['name'=>'张三2','gender'=>'men2']));//往有序集合中添加相应数据 分数为过期事件 val 为要进行改变的数据
var_dump($redis->zRange('delay_queue',0,-1));//查看有序集合的数据
} catch(RedisException $e) {
echo $e->getMessage();
}
2.进行处理的文件
<?php
/**
* redis 延迟队列 消费
*/
try {
$redis = new redis(); //生成redis对象
$redis->connect('127.0.0.1',6379);//连接redis 默认端口6379
$redis->ping();//查询是否连接上,链接不上抛出异常。
//进行处理
while (true) {
$task = $redis->zRangeByScore('delay_queue',0,time(),['limit'=>[0,1]]);//获取集合中过期的数据首个
//如果没有消息队列就返回false
if (!$task){
return false;
}
//这里进行删除,原因可能同时会有多个进程或者线程获取到相同的任务(避免重复操作)
if ($redis->zRem('delay_queue',$task[0])) {
$taskData = json_decode($task[0],true);
//业务逻辑
continue;
} else {
return false;
echo '失败';
}
// array(2) { ["name"]=> string(7) "张三2" ["gender"]=> string(4) "men2" }
}
} catch(RedisException $e) {
echo $e->getMessage();
}
思路整理
- 订单生成,往redis有序集合里添加数据,zadd(有序集合名称, 过期时间,逻辑需要用的数据 (订单ID))。
- 然后通过多个线程运行文件2,最好在文件2里面在加个usleep睡觉,不然的话一直循环会导致性能下降。