php使用redis的有序集合zset实现延迟队列应用示例

本文实例讲述了php使用redis的有序集合zset实现延迟队列。分享给大家供大家参考,具体如下:

延迟队列就是个带延迟功能的消息队列,相对于普通队列,它可以在指定时间消费掉消息。

延迟队列的应用场景:

1、新用户注册,10分钟后发送邮件或站内信。

2、用户下单后,30分钟未支付,订单自动作废。

我们通过redis的有序集合zset来实现简单的延迟队列,将消息数据序列化,作为zset的value,把消息处理时间作为score,每次通过zRangeByScore获取一条消息进行处理。

<?php
class DelayQueue
{
  protected $prefix = 'delay_queue:';
  protected $redis = null;
  protected $key = '';
  public function __construct($queue, $config = [])
  {
    $this->key = $this->prefix . $queue;
    $this->redis = new Redis();
    $this->redis->connect($config['host'], $config['port'], $config['timeout']);
    $this->redis->auth($config['auth']);
  }
  public function delTask($value)
  {
    return $this->redis->zRem($this->key, $value);
  }
  public function getTask()
  {
    //获取任务,以0和当前时间为区间,返回一条记录
    return $this->redis->zRangeByScore($this->key, 0, time(), ['limit' => [0, 1]]);
  }
  public function addTask($name, $time, $data)
  {
    //添加任务,以时间作为score,对任务队列按时间从小到大排序
    return $this->redis->zAdd(
      $this->key,
      $time,
      json_encode([
        'task_name' => $name,
        'task_time' => $time,
        'task_params' => $data,
      ], JSON_UNESCAPED_UNICODE)
    );
  }
  public function run()
  {
    //每次只取一条任务
    $task = $this->getTask();
    if (empty($task)) {
      return false;
    }
    $task = $task[0];
    //有并发的可能,这里通过zrem返回值判断谁抢到该任务
    if ($this->delTask($task)) {
      $task = json_decode($task, true);
      //处理任务
      echo '任务:' . $task['task_name'] . ' 运行时间:' . date('Y-m-d H:i:s') . PHP_EOL;
      return true;
    }
    return false;
  }
}
$dq = new DelayQueue('close_order', [
  'host' => '127.0.0.1',
  'port' => 6379,
  'auth' => '',
  'timeout' => 60,
]);
$dq->addTask('close_order_111', time() + 30, ['order_id' => '111']);
$dq->addTask('close_order_222', time() + 60, ['order_id' => '222']);
$dq->addTask('close_order_333', time() + 90, ['order_id' => '333']);

然后,我们写一个php脚本,用来处理队列中的任务。

<?php
set_time_limit(0);
$dq = new DelayQueue('close_order', [
  'host' => '127.0.0.1',
  'port' => 6379,
  'auth' => '',
  'timeout' => 60,
]);
while (true) {
  $dq->run();
  usleep(100000);
}

更多关于PHP相关内容感兴趣的读者可查看本站专题:《php+redis数据库程序设计技巧总结》、《php面向对象程序设计入门教程》、《PHP基本语法入门教程》、《PHP数组(Array)操作技巧大全》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》

希望本文所述对大家PHP程序设计有所帮助。

(0)

相关推荐

  • PHP的Laravel框架结合MySQL与Redis数据库的使用部署

    相对于熟读官方文档,更重要的是要把框架环境搭起来. 零.环境介绍 操作系统:centOS 数据库: mysql 5.6 (阿里云RDS) PHP 5.4.4 (>=5.4即可) Laravel 5.0 一.安装LNMP 在安装Laravel之前,需要把Linux + Nginx + Mysql + Php的环境搭建好.具体的搭建步骤这里就不再详述了. P.S. Linux阿里云已经自带了,本文使用的是centOS 6.5 64位的ECS 关于Nginx和Apache的选择看自己喜好,本文使用的是

  • PHP操作Redis数据库常用方法示例

    本文实例讲述了PHP操作Redis数据库常用方法.分享给大家供大家参考,具体如下: Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. Redis支持的数据类型有 Stirng(字符串), List(列表), Hash(字典), Set(集合), Sorted Set(有序集合); redis版本是Redis 2.6.12 系统是在Windows+Apache2.4+php5.6 连接: //实例化redis

  • php使用redis的几种常见操作方式和用法示例

    本文实例讲述了php使用redis的几种常见操作方式和用法.分享给大家供大家参考,具体如下: 一.简单的字符串缓存 比如针对一些sql查询较慢,更新不频繁的数据进行缓存. <?php $redis = new Redis(); $redis->connect('127.0.0.1', 6379, 60); $sql = 'select * from tb_order order by id desc limit 10'; //伪代码,从数据库中获取数据 $data = $db->quer

  • redis+php实现微博(一)注册与登录功能详解

    本文实例讲述了redis+php实现微博注册与登录功能.分享给大家供大家参考,具体如下: (一).微博功能概况 微博用户账号注册 微博用户登录 微博发布 添加微博好友(粉丝) 微博推送 微博冷数据写入mysql数据库 (二).redis数据结构设计 这节分享微博用户注册与登录: 我们完全采用redis作为数据库来实现注册于登录 先来看一下redis数据结构的设计: 注册用户表:user set global:userid set user:userid:1:username zhangshan

  • PHP商品秒杀问题解决方案实例详解【mysql与redis】

    本文实例讲述了PHP商品秒杀问题解决方案.分享给大家供大家参考,具体如下: 引言 假设num是存储在数据库中的字段,保存了被秒杀产品的剩余数量. if($num > 0){ //用户抢购成功,记录用户信息 $num--; } 假设在一个并发量较高的场景,数据库中num的值为1时,可能同时会有多个进程读取到num为1,程序判断符合条件,抢购成功,num减一.这样会导致商品超发的情况,本来只有10件可以抢购的商品,可能会有超过10个人抢到,此时num在抢购完成之后为负值. 解决该问题的方案由很多,可

  • php操作redis数据库常见方法实例总结

    本文实例讲述了php操作redis数据库常见方法.分享给大家供大家参考,具体如下: 一.安装php_redis扩展,用以操作redis http://pecl.php.net/package/redis 选择自已系统php版本对应的扩展. 二.redis连接与验证 <?php //创建一个redis客户端 $redis = new Redis(); //连接redis服务,指定主机,端口,和超时时间 $redis->connect('127.0.0.1', 6379, 60); //进行密码验

  • php实现redis数据库指定库号迁移的方法

    本文实例讲述了php实现redis数据库指定库号迁移的方法,分享给大家供大家参考.具体如下: redis普通的数据库迁移,只能整个redis save,或者利用主从,当然也可以安装一个redis-dump,不过比较麻烦,这里提供一种php的脚本,实现指定库号的迁移,其实也就是遍历根据存储类型,读出来,插入新库,效果是这样: 复制代码 代码如下: [root@localhost ~]# php 1.php 1/407 101/407 201/407 301/407 401/407 PHP实例代码如

  • PHP+redis实现的限制抢购防止商品超发功能详解

    本文实例讲述了PHP+redis实现的限制抢购防止商品超发功能.分享给大家供大家参考,具体如下: redis不仅仅是单纯的缓存,它还有一些特殊的功能,在一些特殊场景上很好用.redis中key的原子自增incrby和判断key不存在再写入的setnx方法,可以有效的防止超发. 下面使用两个不同的方式来说明利用redis做商品购买库存数量限制. 业务场景很简单,就是限制抢购5个商品,模拟并发请求抢购商品,每抢购一次对应redis中的key值增加一次,通过判断限购的数量来限制抢购,抢购成功写入成功日

  • redis+php实现微博(三)微博列表功能详解

    本文实例讲述了redis+php实现微博列表功能.分享给大家供大家参考,具体如下: 个人主页显示微博列表(自己及关注人的微博列表) /*获取最新的50微博信息列表,列出自己发布的微博及我关注用户的微博 *1.根据推送的信息获取postid *2.根据postid获取发送的信息 */ $r->ltrim("recivepost:".$user['userid'],0,49); $postid_arr = $r->sort("recivepost:".$us

  • redis+php实现微博(二)发布与关注功能详解

    本文实例讲述了redis+php实现微博发布与关注功能.分享给大家供大家参考,具体如下: 数据结构: set post:postid:3:time timestamp set post:postid:3:userid 5 set post:postid:3:content 测试发布哈哈哈哈 incr global:postid set post:postid:$postidcho "用户名密码不能够为空!"; 关注微博 following:3 被关注(粉丝) followed:3 把发

随机推荐