浅谈Laravel队列实现原理解决问题记录


Posted in PHP onAugust 19, 2017

问题

公司项目使用Laravel的开发的两个项目在同一个测试服务器部署,公用同一个redis。在使用laravel中的队列时,产生冲突干扰。

查找问题原因

在laravel 队列的操作类Illuminate\Queue\RedisQueue.php中可以看到pushRaw()方法:

// 将一任务推入队列中
public function pushRaw($payload, $queue = null, array $options = [])
  {
    $this->getConnection()->rpush($this->getQueue($queue), $payload);

    return Arr::get(json_decode($payload, true), 'id');
  }

从该方法中可以看出Lrarvel队列的redis实现是通过list结构实现的,rpush(key, value)是将value推入键值为key的redis队列,key的值则是通过$this->getQueue($queue) 获取到的

protected function getQueue($queue)
  {
    return 'queues:'.($queue ?: $this->default);
  }

所以的redis中list中的key是 'queues:'.($queue ?: $this->default);拼接的,$this->default 的值是 RedisQueue 实例化的时候从config\queue.php配置中加载的 'queue' => 'default',$queue 是添加队列时$this->dispatch( new jobClass()->onQueue($queue) )传入的。

// config\queue.php 文件中的redis配置部分
'redis' => [
      'driver'   => 'redis',
      'connection' => 'default',
      'queue'   => 'default',
      'expire'   => 60,
    ],

至此,两个项目的队列冲突原因就找到了。因为redis队列配置中 'queue' => 'default' 都使用的默认的default,所以当共用redis时,默认的队列list 都是'queue:default',所以导致了冲突。

因为队列监听 监听的队列名称是由 --queue参数决定的,如果不传就是我们上面设置的默认值,若传了就会根据传入的队列名从前往后优先依次处理,具体见代码Illuminate\Queue\Worker.php中:

protected function getNextJob($connection, $queue)
  {
    if (is_null($queue)) {
      return $connection->pop();
    }

    foreach (explode(',', $queue) as $queue) {
      if (! is_null($job = $connection->pop($queue))) {
        return $job;
      }
    }
  }

$queue就是--queue=传入的参数,当 $queue不存在是直接调用$connection->pop()当参数存在时会将参数解析,优先处理排在前面的队列名称,将队列名称传入pop($queue), pop()会尝试从指定队列或默认队列中获取队列任务

// Illuminate\Queue\RedisQueue.php
public function pop($queue = null)
  {
    $original = $queue ?: $this->default;

    $queue = $this->getQueue($queue);

    if (! is_null($this->expire)) {
      $this->migrateAllExpiredJobs($queue);
    }

    $job = $this->getConnection()->lpop($queue);

    if (! is_null($job)) {
      $this->getConnection()->zadd($queue.':reserved', $this->getTime() + $this->expire, $job);

      return new RedisJob($this->container, $this, $job, $original);
    }
  }

至此搞清了队列执行的原理。

解决方法

将queue的配置文件中默认队列修改为不同的名称,比如: 'queue' => laravel1','queue' => laravel2'。

队列监听 php artisan queue:listen redis --queue=laravel1,syncExpress

最后

遇到问题,莫要病急乱投医。从代码入手,分析理解实现原理,找对点,解决方法也许很简单,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
php 生成静态页面的办法与实现代码详细版
Feb 15 PHP
php绝对路径与相对路径之间关系的的分析
Mar 03 PHP
分享一个PHP数据流应用的简单例子
Jun 01 PHP
PHP在线生成二维码(google api)的实现代码详解
Jun 04 PHP
PHP函数shuffle()取数组若干个随机元素的方法分析
Apr 02 PHP
PHP创建多级目录的两种方法
Oct 28 PHP
Laravel中如何增加自定义全局函数详解
May 09 PHP
php实现评论回复删除功能
May 23 PHP
利用php的ob缓存机制实现页面静态化方法
Jul 09 PHP
Laravel学习教程之request validation的编写
Oct 25 PHP
PHP实现通过CURL上传文件功能示例
May 30 PHP
PHP设计模式(五)适配器模式Adapter实例详解【结构型】
May 02 PHP
yii2 commands模式以及配置crontab定时任务的方法
Aug 19 #PHP
利用 fsockopen() 函数开放端口扫描器的实例
Aug 19 #PHP
PHPMailer使用QQ邮箱实现邮件发送功能
Aug 18 #PHP
PHP实现自动发送邮件功能代码(qq 邮箱)
Aug 18 #PHP
详解PHP如何更好的利用PHPstorm的自动提示
Aug 18 #PHP
Laravel学习教程之本地化模块
Aug 18 #PHP
PDO操作MySQL的基础教程(推荐)
Aug 18 #PHP
You might like
php 读取shell管道传输过来的内容
2010/03/01 PHP
解析php根据ip查询所在地区(非常有用,赶集网就用到)
2013/07/01 PHP
php curl模拟post请求小实例
2013/11/13 PHP
回帖脱衣服的图片实现代码
2014/02/15 PHP
php递归调用删除数组空值元素的方法
2015/04/28 PHP
php实现图片按比例截取的方法
2017/02/06 PHP
Javascript的各种节点操作实例演示代码
2012/06/27 Javascript
jquery可见性过滤选择器使用示例
2013/06/24 Javascript
JS.elementGetStyle(element, style)应用示例
2013/09/24 Javascript
JavaScript字符串对象slice方法入门实例(用于字符串截取)
2014/10/16 Javascript
JavaScript中的Function函数
2015/08/27 Javascript
悬浮广告方法日常收集整理
2016/03/18 Javascript
jQuery 跨域访问解决原理案例详解
2016/07/09 Javascript
JavaScript交换两个变量值的七种解决方案
2016/12/01 Javascript
原生JS实现图片轮播切换效果
2016/12/15 Javascript
深入理解Angularjs向指令传递数据双向绑定机制
2016/12/31 Javascript
jQuery模拟爆炸倒计时功能实例代码
2017/08/21 jQuery
JS实现的文件拖拽上传功能示例
2018/05/21 Javascript
Vue ElementUi同时校验多个表单(巧用new promise)
2018/06/06 Javascript
vue-cli项目代理proxyTable配置exclude的方法
2018/09/20 Javascript
layui当点击文本框时弹出选择框,显示选择内容的例子
2019/09/02 Javascript
vue cli3 调用百度翻译API翻译页面的实现示例
2019/09/13 Javascript
vue-preview动态获取图片宽高并增加旋转功能的实现
2020/07/29 Javascript
[14:51]DOTA2 HEROS教学视频教你分分钟做大人-卓尔游侠
2014/06/13 DOTA
Python实现针对给定单链表删除指定节点的方法
2018/04/12 Python
mac安装pytorch及系统的numpy更新方法
2018/07/26 Python
python线程安全及多进程多线程实现方法详解
2019/09/27 Python
Pandas数据分析的一些常用小技巧
2021/02/07 Python
澳大利亚领先的美容护肤品零售商之一:SkincareStore
2018/01/22 全球购物
招聘单位介绍信
2014/01/14 职场文书
三年级数学教学反思
2014/01/31 职场文书
幼儿园小班评语
2014/04/18 职场文书
法学求职信
2014/06/22 职场文书
民主评议政风行风活动心得体会
2014/10/29 职场文书
党风廉正建设个人工作总结
2015/03/06 职场文书
2015年电厂工作总结范文
2015/05/13 职场文书