浅谈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中截取字符串支持utf-8
Jan 18 PHP
php中对2个数组相加的函数
Jun 24 PHP
Yii 快速,安全,专业的PHP框架
Sep 03 PHP
PHP中substr()与explode()函数用法分析
Nov 24 PHP
php构造函数的继承方法
Feb 09 PHP
Laravel中使用阿里云OSS Composer包分享
Feb 10 PHP
PDO防注入原理分析以及注意事项
Feb 25 PHP
php实现指定字符串中查找子字符串的方法
Mar 17 PHP
几个优化WordPress中JavaScript加载体验的插件介绍
Dec 17 PHP
php中类和对象:静态属性、静态方法
Apr 09 PHP
php实现生成PDF文件的方法示例【基于FPDF类库】
Jul 21 PHP
PHP过滤器 filter_has_var() 函数用法实例分析
Apr 23 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模板引擎Smarty的缓存使用总结
2014/04/24 PHP
dedecms中使用php语句指南
2014/11/13 PHP
PHP实现linux命令tail -f
2016/02/22 PHP
thinkPHP统计排行与分页显示功能示例
2016/12/02 PHP
Laravel等框架模型关联的可用性浅析
2019/12/15 PHP
[对联广告] JS脚本类
2006/08/27 Javascript
javascript SocialHistory 检查访问者是否访问过某站点
2008/08/02 Javascript
使用JavaScript动态设置样式实现代码(2)
2013/01/25 Javascript
当json键为数字时的取值方法解析
2013/11/15 Javascript
javascript中处理时间戳为日期格式的方法
2014/01/02 Javascript
用JavaScript实现用一个DIV来包装文本元素节点
2014/09/09 Javascript
JavaScript取得WEB安全颜色列表的方法
2015/07/14 Javascript
AngularJS directive返回对象属性详解
2016/03/28 Javascript
node.js连接MongoDB数据库的2种方法教程
2017/05/17 Javascript
详解Angular2响应式表单
2017/06/14 Javascript
解决webpack -p压缩打包react报语法错误的方法
2017/07/03 Javascript
vue填坑之webpack run build 静态资源找不到的解决方法
2018/09/03 Javascript
vue与原生app的对接交互的方法(混合开发)
2018/11/28 Javascript
解决layer弹出层中表单不起作用的问题
2019/09/09 Javascript
跟老齐学Python之做一个小游戏
2014/09/28 Python
Python实现的HMacMD5加密算法示例
2018/04/03 Python
python实现Flappy Bird源码
2018/12/24 Python
python3实现弹弹球小游戏
2019/11/25 Python
解决 jupyter notebook 回车换两行问题
2020/04/15 Python
python实现猜单词游戏
2020/05/22 Python
Python命令行参数argv和argparse该如何使用
2021/02/08 Python
利用CSS3实现自定义滚动条代码分享
2016/08/18 HTML / CSS
基于CSS3特效之动画:animation的应用
2013/05/09 HTML / CSS
Grow Gorgeous美国官网:只要八天,体验唤醒毛囊后新生的茂密秀发
2018/06/04 全球购物
中国专业的音频分享平台:喜马拉雅
2019/05/24 全球购物
2014元旦晚会策划方案
2014/02/19 职场文书
无传销社区工作方案
2014/05/13 职场文书
党员“一帮一”活动总结
2015/05/07 职场文书
刑事撤诉申请书
2015/05/18 职场文书
财务年终工作总结大全
2019/06/20 职场文书
Python使用Opencv打开笔记本电脑摄像头报错解问题及解决
2022/06/21 Python