浅谈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 相关文章推荐
discuz加密解密函数使用方法和中文注释
Jan 21 PHP
3个PHP多维数组转为一维数组的方法实例
Mar 13 PHP
PHP fopen()和 file_get_contents()应用与差异介绍
Mar 19 PHP
PHP中的gzcompress、gzdeflate、gzencode函数详解
Jul 29 PHP
ecshop适应在PHP7的修改方法解决报错的实现
Nov 01 PHP
PHP读取文件的常见几种方法
Nov 03 PHP
Yii 2.0在Grid中格式化时间方法示例
Jun 06 PHP
thinkphp查询,3.X 5.0方法(亲试可行)
Jun 17 PHP
PHP使用redis消息队列发布微博的方法示例
Jun 22 PHP
彻底搞懂PHP 变量结构体
Oct 11 PHP
PHP实现搜索时记住状态的方法示例
May 11 PHP
PHP登录验证功能示例【用户名、密码、验证码、数据库、已登陆验证、自动登录和注销登录等】
Feb 25 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
深入mysql_fetch_row()与mysql_fetch_array()的区别详解
2013/06/05 PHP
php遍历文件夹所有文件子文件夹函数代码
2013/11/27 PHP
PHP 如何获取二维数组中某个key的集合
2014/06/03 PHP
php实现字符串反转输出的方法
2015/03/14 PHP
解读PHP的Yii框架中请求与响应的处理流程
2016/03/17 PHP
js获取url参数的使用扩展实例
2007/12/29 Javascript
关于javascript中的parseInt使用技巧
2009/09/03 Javascript
JQuery下关于$.Ready()的分析
2009/12/13 Javascript
jQuery编辑器KindEditor4.1.4代码高亮显示设置教程
2013/03/01 Javascript
非常酷炫的Bootstrap图片轮播动画
2016/05/27 Javascript
一步一步封装自己的HtmlHelper组件BootstrapHelper(二)
2016/09/14 Javascript
微信 java 实现js-sdk 图片上传下载完整流程
2016/10/21 Javascript
如何防止INPUT按回车自动提交表单FORM
2016/12/06 Javascript
基于jQuery实现的查看全文功能【实用】
2016/12/11 Javascript
详解js中Number()、parseInt()和parseFloat()的区别
2016/12/20 Javascript
JavaScript中附件预览功能实现详解(推荐)
2017/08/15 Javascript
详谈构造函数加括号与不加括号的区别
2017/10/26 Javascript
安装Node.js并启动本地服务的操作教程
2018/05/12 Javascript
[03:03]DOTA2 2017国际邀请赛开幕战队入场仪式
2017/08/09 DOTA
[43:49]LGD vs CHAOS 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
python3模拟百度登录并实现百度贴吧签到示例分享(百度贴吧自动签到)
2014/02/24 Python
Python中的字符串类型基本知识学习教程
2016/02/04 Python
Python 专题三 字符串的基础知识
2017/03/19 Python
Python http接口自动化测试框架实现方法示例
2018/12/06 Python
python 使用matplotlib 实现从文件中读取x,y坐标的可视化方法
2019/07/04 Python
python自带tkinter库实现棋盘覆盖图形界面
2019/07/17 Python
通过python调用adb命令对App进行性能测试方式
2020/04/23 Python
python os模块在系统管理中的应用
2020/06/22 Python
Snapfish爱尔兰:在线照片打印和个性化照片礼品
2018/09/17 全球购物
求职推荐信范文
2013/12/01 职场文书
服装厂厂长职责
2013/12/16 职场文书
给女儿的表扬信
2014/01/18 职场文书
大学生求职信范文
2014/05/24 职场文书
2014财务部年度工作总结
2014/12/08 职场文书
绵山导游词
2015/02/05 职场文书
质量负责人岗位职责
2015/02/15 职场文书