刘少星


人的一切痛苦,本质上都是对自己无能的愤怒。加油!


welcome to mine blog !

Laravel中使用Redis作为队列系统的工作流程

利用Redis可以很方便的实现一个任务队列,但是在Laravel中,Redis的队列总会出现一个任务多次执行的问题。究其原因是它写死了reserved的时长,也就是如果1分钟后任务没有执行完成,那么这个任务就会被重新放回队列。下面是队列的简单使用和执行原理。

设置

设置队列使用Redis非常容易,在app/config/queue.php中配置

...
'default' => 'redis',
...
'connections' => array(
    ...
    'redis' => array(
        'driver' => 'redis',
        'queue'  => 'waa',
    ),
),

即可。

使用

使用时不需要多配置,只要写好Queue类和其fire方法,在需要的位置出队即可。具体方法可以看这里

class SendEmail {

    public function fire($job, $data)
    {
        //
        $job->delete();
    }

}

Queue::push('SendEmail@send', array('message' => $message));

流程

Laravel利用artisan命令来执行出队操作,然后进行任务的执行。方法调用如下:

  1. artisan queue:work
  2. WorkerCommand:fire()
  3. Worker:pop()
  4. Worker:getNextJob()
  5. RedisQueue:pop()
  6. Worker:process()

我遇到的问题就在这里,在RedisQueue:pop()方法中,有这样一句:

$this->redis->zadd($queue.':reserved', $this->getTime() + 60, $job);

这里将当前执行的任务放到另外一个reserved队列中,超时时间是60s。也就是说,如果60s后这个任务没有被删除掉,则任务会重新被放入队列中来。因此,在实际的使用过程中,任务很可能被多次执行。解决的办法是

class SendEmail {

    public function fire($job, $data)
    {
        $job->delete();
        // job 
    }

}

即先删除这个任务,再开始执行任务。

最近的文章

MySQL大量数据插入各种方法性能分析与比较

不管是日常业务数据处理中,还是数据库的导入导出,都可能遇到需要处理大量数据的插入。插入的方式和数据库引擎都会对插入速度造成影响,这篇文章旨在从理论和实践上对各种方法进行分析和比较,方便以后应用中插入方法的选择。插入分析MySQL中插入一个记录需要的时间由下列因素组成,其中的数字表示大约比例:连接:(3)发送查询给服务器:(2)分析查询:(2)插入记录:(1x记录大小)插入索引:(1x索引)关闭:(1)如果我们每插入一条都执行一个SQL语句,那么我们需要执行除了连接和关闭之外的所有步骤N次,...…

MySQL继续阅读
更早的文章

使用Supervisor来管理你的Laravel队列

Laravel官网教程中,并没有提到用它来写CLI应用,即守护进程或者可执行脚本。但是它却提供了更加便捷的队列(Queue)功能。Laravel队列我们在开发应用过程中难免会遇到处理耗时任务的需求,这些任务如果直接在用户的请求中处理,必然会导致页面显示被阻塞。虽然利用fastcgi的一些特性可以先输出页面,后台任务继续执行,但是这样远远不如将任务交给异步队列来处理方便。配置和启动Laravel队列功能为我们提供了一个便捷的方式去处理这些异步任务,配置一个队列只需要以下几步:配置app/co...…

LaravelPHP继续阅读