浅谈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 相关文章推荐
用Flash图形化数据(一)
Oct 09 PHP
dedecms 制作模板中使用的全局标记图文教程
Mar 11 PHP
PHP中基本符号及使用方法
Mar 23 PHP
php excel类 phpExcel使用方法介绍
Aug 21 PHP
PHP imagecreatefrombmp 从BMP文件或URL新建一图像
Jul 16 PHP
ucenter通信原理分析
Jan 09 PHP
PHP输出日历表代码实例
Mar 27 PHP
PHP生成静态HTML文档实现代码
Jun 23 PHP
thinkphp Apache配置重启Apache1 restart 出错解决办法
Feb 15 PHP
PHP图片水印类的封装
Jul 06 PHP
PHP排序算法之快速排序(Quick Sort)及其优化算法详解
Apr 21 PHP
PHP中localeconv()函数的用法
Mar 26 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
成本8450万,票房仅2亿,口碑两极分化,又一部DC电影扑街了
2020/04/09 欧美动漫
解析PHP中的正则表达式以及模式匹配
2013/06/19 PHP
PHP动态编译出现Cannot find autoconf的解决方法
2014/11/05 PHP
php实现在多维数组中查找特定value的方法
2015/07/29 PHP
必须收藏的23个php实用代码片段
2016/02/02 PHP
php实现图片上传时添加文字和图片水印技巧
2020/04/18 PHP
yii 框架实现按天,月,年,自定义时间段统计数据的方法分析
2020/04/04 PHP
PHP 99乘法表的几种实现代码
2020/10/13 PHP
BOOM vs RR BO5 第四场 2.14
2021/03/10 DOTA
用JavaScript隐藏控件的方法
2009/09/21 Javascript
对setInterval在火狐和chrome切换标签产生奇怪的效果之探索,与解决方案!
2011/10/29 Javascript
a标签的href与onclick事件的区别详解
2014/11/12 Javascript
jQuery实现表格颜色交替显示的方法
2015/03/09 Javascript
基于jQuery实现仿百度首页换肤背景图片切换代码
2015/08/25 Javascript
解决js页面滚动效果scrollTop在FireFox与Chrome浏览器间的兼容问题的方法
2015/12/03 Javascript
详解使用fetch发送post请求时的参数处理
2017/04/05 Javascript
ES6入门教程之let和const命令详解
2017/05/17 Javascript
AngularJS实现表单元素值绑定操作示例
2017/10/11 Javascript
Node.js使用Koa搭建 基础项目
2018/01/08 Javascript
Vue 实现监听窗口关闭事件,并在窗口关闭前发送请求
2020/09/01 Javascript
Electron+vue从零开始打造一个本地播放器的方法示例
2020/10/27 Javascript
[02:55]DOTA2英雄基础教程 发条技师
2013/12/04 DOTA
[40:01]OG vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
详解python中sort排序使用
2019/03/23 Python
python 计算平均平方误差(MSE)的实例
2019/06/29 Python
python画双y轴图像的示例代码
2019/07/07 Python
利用pandas合并多个excel的方法示例
2019/10/10 Python
python GUI库图形界面开发之PyQt5输入对话框QInputDialog详细使用方法与实例
2020/02/27 Python
python字典的值可以修改吗
2020/06/29 Python
西班牙最大的在线滑板和街头服饰商店:Fillow.net
2019/04/15 全球购物
办理生育手续介绍信
2014/01/14 职场文书
施工员岗位职责
2014/03/16 职场文书
加多宝凉茶广告词
2014/03/18 职场文书
《毛主席在花山》教学反思
2014/04/20 职场文书
地方白酒代理协议书
2014/10/25 职场文书
2014年服务员工作总结
2014/11/18 职场文书