美文网首页
redis实现简单的延迟队列

redis实现简单的延迟队列

作者: 一梦三四年lyp | 来源:发表于2019-07-19 17:10 被阅读0次
    <?php
    /**
     * Created by PhpStorm.
     * User: Administrator
     * Date: 2019/7/17
     * Time: 9:27
     */
    set_time_limit(0);
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    
    $delayQueue = 'delay:queue';
    
    $redis->zAdd($delayQueue, time() + 30,
    json_encode(['id' => 11, 'content' => 'test test', 'email' => '998989@qq.com', 'name' => 'lww']));
    echo "插入成功" . PHP_EOL;
    //$redis->zAdd($delayQueue, time() + 120, json_encode(['id'=>2,'content' => 'test2 test2', 'email' => '998989@qq.com', 'name' => 'lww']));
    
    //添加锁
    function addLock($lockName, $timeout = 0)
    {
    global $redis;
    //唯一标识
    $identifier = uniqid();
    //设置过期时间
    $nowTime = time();
    $endTime = $nowTime + $timeout;
    
    while ($endTime >= $nowTime) {
        if ($redis->setnx($lockName, $identifier)) {
            return $identifier;
        } else {
            return false;
        }
    }
    
    return false;
    }
    
    function releaseLock($lockName, $identifier)
    {
    global $redis;
    while (true) {
       // $redis->watch($lockName);
       // var_dump($redis->get($lockName),$identifier );die;
        if ($redis->get($lockName) == $identifier) {
            //释放锁,即删除该key值
            $redis->del($lockName);
            return true;
        } else {
            //获取不到值说明,锁已经释放掉了,这时候不需要再监控这个锁值
            //$redis->unwatch($lockName);
    
            return false;
        }
    }
    
    }
    
    while (true) {
    //获取有序集合里面的值,执行时间作为有序集合的分值
    $firstDelayTask = $redis->zRange($delayQueue, 0, 0, true);
    if (empty($firstDelayTask)) {
        echo "没有可以执行的任务" . PHP_EOL;
        sleep(1);
        continue;
    }
    
    //获取任务值
    $taskJson = key($firstDelayTask);
    $delayTime = current($firstDelayTask);
    $taskValue = json_decode($taskJson, true);
    $nowTime = time();
    
    
    if ($delayTime <= $nowTime) {
        //小于或等于当前时间,说明要去执行该任务。为了保证一致性,所以选择加锁操作
        $lock = 'id:' . $taskValue['id'];
    
        if (!($identifier = addLock($lock))) {
            echo "获取锁失败" . PHP_EOL;
            //加锁失败,则从新执行
            continue;
        }
        //加锁成功,将任务移动到执行队列里
        $redis->multi();
        //将任务从延迟队列移除
        $redis->zRem($delayQueue, $taskJson);
        //添加到执行队列里
        $redis->rPush('execute:queue', $taskJson);
        // 释放锁,执行完了开始释放锁
        $redis->del($lock);
          //  return true;
        $result = $redis->exec();
    
        //判断事务是否成功
        if (isset($result[0]) && $result[0] == 1) {
            echo 'Successful task execution' . PHP_EOL;
        } else {
            $redis->discard();
            echo "提交失败111" . PHP_EOL;
        }
    }
    }

    相关文章

      网友评论

          本文标题:redis实现简单的延迟队列

          本文链接:https://www.haomeiwen.com/subject/mbmslctx.html