当前位置:首页 > PHP教程 > php高级应用 > 列表

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

发布:smiling 来源: PHP粉丝网  添加日期:2022-02-12 11:02:14 浏览: 评论:0 

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

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

延迟队列的应用场景:

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

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

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

  1. <?php 
  2. class DelayQueue 
  3.   protected $prefix = 'delay_queue:'
  4.   protected $redis = null; 
  5.   protected $key = ''
  6.   public function __construct($queue$config = []) 
  7.   { 
  8.     $this->key = $this->prefix . $queue
  9.     $this->redis = new Redis(); 
  10.     $this->redis->connect($config['host'], $config['port'], $config['timeout']); 
  11.     $this->redis->auth($config['auth']); 
  12.   } 
  13.   public function delTask($value
  14.   { 
  15.     return $this->redis->zRem($this->key, $value); 
  16.   } 
  17.   public function getTask() 
  18.   { 
  19.     //获取任务,以0和当前时间为区间,返回一条记录 
  20.     return $this->redis->zRangeByScore($this->key, 0, time(), ['limit' => [0, 1]]); 
  21.   } 
  22.   public function addTask($name$time$data
  23.   { 
  24.     //添加任务,以时间作为score,对任务队列按时间从小到大排序 
  25.     return $this->redis->zAdd( 
  26.       $this->key, 
  27.       $time
  28.       json_encode([ 
  29.         'task_name' => $name
  30.         'task_time' => $time
  31.         'task_params' => $data
  32.       ], JSON_UNESCAPED_UNICODE) 
  33.     ); 
  34.   } 
  35.   public function run() 
  36.   { 
  37.     //每次只取一条任务 
  38.     $task = $this->getTask(); 
  39.     if (emptyempty($task)) { 
  40.       return false; 
  41.     } 
  42.     $task = $task[0]; 
  43.     //有并发的可能,这里通过zrem返回值判断谁抢到该任务 
  44.     if ($this->delTask($task)) { 
  45.       $task = json_decode($task, true); 
  46.       //处理任务 
  47.       echo '任务:' . $task['task_name'] . ' 运行时间:' . date('Y-m-d H:i:s') . PHP_EOL; 
  48.       return true; 
  49.     } 
  50.     return false; 
  51.   } 
  52. $dq = new DelayQueue('close_order', [ 
  53.   'host' => '127.0.0.1'
  54.   'port' => 6379, 
  55.   'auth' => ''
  56.   'timeout' => 60, 
  57. ]); 
  58. $dq->addTask('close_order_111', time() + 30, ['order_id' => '111']); 
  59. $dq->addTask('close_order_222', time() + 60, ['order_id' => '222']); 
  60. $dq->addTask('close_order_333', time() + 90, ['order_id' => '333']); 

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

  1. <?php 
  2. set_time_limit(0); 
  3. $dq = new DelayQueue('close_order', [ 
  4.   'host' => '127.0.0.1'
  5.   'port' => 6379, 
  6.   'auth' => ''
  7.   'timeout' => 60, 
  8. ]); 
  9. while (true) { 
  10.   $dq->run(); 
  11.   usleep(100000); 
  12. }

Tags: redis有序集合 zset

分享到: