浅谈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 相关文章推荐
为php4加入动态flash文件的生成的支持
Oct 09 PHP
从网上搜到的phpwind 0day的代码
Dec 07 PHP
php数据库连接时容易出错的特殊符号问题
Sep 01 PHP
php递归创建和删除文件夹的代码小结
Apr 13 PHP
php 邮件发送问题解决
Mar 22 PHP
一个简单的PHP验证码实现代码
May 10 PHP
PHP嵌套输出缓冲代码实例
May 12 PHP
详解PHP中的null合并运算符
Dec 30 PHP
详解thinkphp中的volist标签
Jan 15 PHP
PHP5.6读写excel表格文件操作示例
Feb 26 PHP
thinkPHP和onethink微信支付插件分享
Aug 11 PHP
PHP 扩展Memcached命令用法实例总结
Jun 04 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静态类的原罪详解
2013/05/06 PHP
PHP设计模式之迭代器模式的深入解析
2013/06/13 PHP
PHP获取数组中指定的一列实例
2017/12/27 PHP
Gird事件机制初级读本
2007/03/10 Javascript
js中的eventType事件及其浏览器支持性介绍
2013/11/29 Javascript
Jquery实现的角色左右选择特效
2014/05/21 Javascript
Javascript基础教程之JavaScript语法
2015/01/18 Javascript
jQuery中DOM树操作之复制元素的方法
2015/01/23 Javascript
基于jQuery实现仿淘宝套餐选择插件
2015/03/04 Javascript
详解JavaScript节流函数中的Throttle
2016/07/16 Javascript
JavaScript下拉菜单功能实例代码
2017/03/01 Javascript
详解webpack和webpack-simple中如何引入css文件
2017/06/28 Javascript
通过 JS 判断页面是否有滚动条的实现方法
2018/04/05 Javascript
vue favicon设置以及动态修改favicon的方法
2018/12/21 Javascript
详解JS浏览器事件循环机制
2019/03/27 Javascript
JavaScript判断浏览器运行环境的详细方法
2019/06/30 Javascript
解决iView Table组件宽度只变大不变小的问题
2020/11/13 Javascript
[01:01:36]Optic vs paiN 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
Python urlopen()函数 示例分享
2014/06/12 Python
python追加元素到列表的方法
2015/07/28 Python
python pyinstaller 加载ui路径方法
2019/06/10 Python
python调试神器PySnooper的使用
2019/07/03 Python
python3.7添加dlib模块的方法
2020/07/01 Python
导致python中import错误的原因是什么
2020/07/01 Python
Python爬取酷狗MP3音频的步骤
2021/02/26 Python
HTML5 SEO优化的一些建议
2020/08/27 HTML / CSS
ECOSUSI官网:女式皮革背包
2019/09/27 全球购物
乌克兰设计师和品牌的服装:Love&Live
2020/04/14 全球购物
如何唤起类中的一个方法
2013/11/29 面试题
大学生职业生涯规划范文
2013/12/31 职场文书
优秀教师先进事迹
2014/01/22 职场文书
踏青活动策划方案
2014/08/19 职场文书
2015年党日活动总结范文
2015/03/25 职场文书
解放思想大讨论活动总结
2015/05/09 职场文书
2016党员党课心得体会
2016/01/07 职场文书
Vue Element UI自定义描述列表组件
2021/05/18 Vue.js