浅谈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个人网站架设连环讲(一)
Oct 09 PHP
yii框架中的Url生产问题小结
Jan 16 PHP
初步介绍PHP扩展开发经验分享
Sep 06 PHP
PHP魔术引号所带来的安全问题分析
Jul 15 PHP
PHPer 需要了解的 5 个 Composer 小技巧
Aug 18 PHP
php密码生成类实例
Sep 24 PHP
php实现编辑和保存文件的方法
Jul 20 PHP
浅析PHP关键词替换的类(避免重复替换,保留与还原原始链接)
Sep 22 PHP
学习php设计模式 php实现模板方法模式
Dec 08 PHP
PHP实现图片不变型裁剪及图片按比例裁剪的方法
Jan 14 PHP
PHP简单实现文本计数器的方法
Apr 28 PHP
PHP Ajax实现无刷新附件上传
Aug 17 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
phpmyadmin里面导入sql语句格式的大量数据的方法
2010/06/05 PHP
Android ProgressBar进度条和ProgressDialog进度框的展示DEMO
2013/06/19 PHP
php图片缩放实现方法
2014/02/20 PHP
PHP基于单例模式编写PDO类的方法
2016/09/13 PHP
PHP微信红包生成代码分享
2016/10/06 PHP
实例分析PHP中PHPMailer发邮件
2017/12/13 PHP
ThinkPHP框架实现定时执行任务的两种方法分析
2018/09/04 PHP
PHP实现微信申请退款功能
2018/10/01 PHP
Yii 实现数据加密和解密
2021/03/09 PHP
ext实现完整的登录代码
2008/08/08 Javascript
使用Jquery获取带特殊符号的ID 标签的方法
2014/04/30 Javascript
JavaScript父子窗体间的调用方法
2015/03/31 Javascript
JS实现动态生成表格并提交表格数据向后端
2020/11/25 Javascript
jQuery EasyUI中DataGird动态生成列的方法
2016/04/05 Javascript
JavaScript编写九九乘法表(两种任选)
2017/02/04 Javascript
jquery实现全选、全不选以及单选功能
2017/03/23 jQuery
vue中使用vue-router切换页面时滚动条自动滚动到顶部的方法
2017/11/28 Javascript
Vue.js 实现微信公众号菜单编辑器功能(一)
2018/05/08 Javascript
了解在JavaScript中将值转换为字符串的5种方法
2019/06/06 Javascript
优化Vue中date format的性能详解
2020/01/13 Javascript
JavaScript枚举选择jquery插件代码实例
2020/11/17 jQuery
[01:02:46]VGJ.S vs NB 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
使用python检测手机QQ在线状态的脚本代码
2013/02/10 Python
利用Python将每日一句定时推送至微信的实现方法
2018/08/13 Python
pytorch 实现将自己的图片数据处理成可以训练的图片类型
2020/01/08 Python
TensorFlow实现指数衰减学习率的方法
2020/02/05 Python
Python实现常见的几种加密算法(MD5,SHA-1,HMAC,DES/AES,RSA和ECC)
2020/05/09 Python
django queryset相加和筛选教程
2020/05/18 Python
python读取图片颜色值并生成excel像素画的方法实例
2021/02/19 Python
pandas apply使用多列计算生成新的列实现示例
2021/02/24 Python
HTML5资源预加载(Link prefetch)详细介绍(给你的网页加速)
2014/05/07 HTML / CSS
大专毕业自我鉴定
2014/02/04 职场文书
实习护士自荐信
2014/06/21 职场文书
2015年教师业务工作总结
2015/05/26 职场文书
Python常用配置文件ini、json、yaml读写总结
2021/07/09 Python
Django框架之路由用法
2022/06/10 Python