浅谈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 相关文章推荐
最省空间的计数器
Oct 09 PHP
PHP nl2br函数 将换行字符转成 <br>
Aug 21 PHP
php下安装配置fckeditor编辑器的方法
Mar 02 PHP
JSON在PHP中的应用介绍
Sep 08 PHP
php使用百度翻译api示例分享
Jan 31 PHP
PHP include任意文件或URL介绍
Apr 29 PHP
PHP自动重命名文件实现方法
Nov 04 PHP
thinkphp3.2.2实现生成多张缩略图的方法
Dec 19 PHP
又十个超级有用的PHP代码片段
Sep 24 PHP
thinkPHP下的widget扩展用法实例分析
Dec 26 PHP
CodeIgniter框架钩子机制实现方法【hooks类】
Aug 21 PHP
thinkphp框架使用JWTtoken的方法详解
Oct 10 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简单选择排序算法实例
2015/01/26 PHP
php实现数组按指定KEY排序的方法
2015/03/30 PHP
PHP环境搭建(php+Apache+mysql)
2016/11/14 PHP
PHP的反射机制实例详解
2017/03/29 PHP
PHP 传输会话curl函数的实例详解
2017/09/12 PHP
PHP htmlspecialchars()函数用法与实例讲解
2019/03/08 PHP
基于jquery的Repeater实现代码
2010/07/17 Javascript
JavaScript字符串对象charAt方法入门实例(用于取得指定位置的字符)
2014/10/17 Javascript
JavaScript实现按照指定长度为数字前面补零输出的方法
2015/03/19 Javascript
微信小程序button组件使用详解
2018/01/31 Javascript
vue单页应用加百度统计代码(亲测有效)
2018/01/31 Javascript
详解VueJS应用中管理用户权限
2018/02/02 Javascript
vue.js 实现点击按钮动态添加li的方法
2018/09/07 Javascript
微信小程序BindTap快速连续点击目标页面跳转多次问题处理
2019/04/08 Javascript
解决Layui 表格自适应高度的问题
2019/11/15 Javascript
vue基于better-scroll仿京东分类列表
2020/06/30 Javascript
python获得两个数组交集、并集、差集的方法
2015/03/27 Python
如何准确判断请求是搜索引擎爬虫(蜘蛛)发出的请求
2015/10/13 Python
Python环境搭建之OpenCV的步骤方法
2017/10/20 Python
对python中xlsx,csv以及json文件的相互转化方法详解
2018/12/25 Python
Python 获取ftp服务器文件时间的方法
2019/07/02 Python
Python通过cv2读取多个USB摄像头
2019/08/28 Python
基于Python实现人脸自动戴口罩系统
2020/02/06 Python
利用python中集合的唯一性实现去重
2020/02/11 Python
Python操作Jira库常用方法解析
2020/04/10 Python
Rakuten Kobo台湾:电子书、eReaders和Reading应用程式
2017/11/24 全球购物
新闻学专业应届生求职信
2013/11/08 职场文书
七一表彰活动方案
2014/01/18 职场文书
二年级语文教学反思
2014/02/02 职场文书
档案室主任岗位职责
2014/02/12 职场文书
土木工程师职业规划范文
2014/03/07 职场文书
2016公司年会主持词
2015/07/01 职场文书
用Python selenium实现淘宝抢单机器人
2021/06/18 Python
2007年老电脑安装win11会怎么样? 网友实测win11在老电脑运行良好
2021/11/21 数码科技
Python函数中apply、map、applymap的区别
2021/11/27 Python
MySQL优化及索引解析
2022/03/17 MySQL