浅谈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面向对象全攻略 (五) 封装性
Sep 30 PHP
PHP性能优化 产生高度优化代码
Jul 22 PHP
php中让上传的文件大小在上传前就受限制的两种解决方法
Jun 24 PHP
浅析php插件 Simple HTML DOM 用DOM方式处理HTML
Jul 01 PHP
zend framework文件上传功能实例代码
Dec 25 PHP
php数组查找函数总结
Nov 18 PHP
php在apache环境下实现gzip配置方法
Apr 02 PHP
php通过baihui网API实现读取word文档并展示
Jun 22 PHP
phpMyAdmin安装并配置允许空密码登录
Jul 04 PHP
详解YII关联查询
Jan 10 PHP
YII框架实现自定义第三方扩展操作示例
Apr 26 PHP
使用composer安装使用thinkphp6.0框架问题【视频教程】
Oct 01 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字符串 ==比较运算符的副作用
2009/10/21 PHP
php生成QRcode实例
2014/09/22 PHP
什么是PEAR?什么是PECL?PHP中两个容易混淆的概念解释
2015/07/01 PHP
ThinkPHP中create()方法自动验证表单信息
2017/04/28 PHP
PHP 中 var_export、print_r、var_dump 调试中的区别
2018/06/19 PHP
php的扩展写法总结
2019/05/14 PHP
laravel框架 api自定义全局异常处理方法
2019/10/11 PHP
JavaScript 常用函数库详解
2009/10/21 Javascript
当jQuery遭遇CoffeeScript的时候 使用分享
2011/09/17 Javascript
js图片自动轮播代码分享(js图片轮播)
2014/05/06 Javascript
举例讲解JavaScript中将数组元素转换为字符串的方法
2015/10/25 Javascript
jQuery formValidator表单验证
2016/01/07 Javascript
JS拉起或下载app的实现代码
2017/02/22 Javascript
详解A标签中href=""的几种用法
2017/08/20 Javascript
JS实现利用两个队列表示一个栈的方法
2017/12/13 Javascript
JavaScript算法学习之冒泡排序和选择排序
2019/11/02 Javascript
小程序自定义模板实现吸顶功能
2020/01/08 Javascript
JS函数本身的作用域实例分析
2020/03/16 Javascript
详解ES6 CLASS在微信小程序中的应用实例
2020/04/24 Javascript
通过实例了解Render Props回调地狱解决方案
2020/11/04 Javascript
Flask框架中密码的加盐哈希加密和验证功能的用法详解
2016/06/07 Python
python爬虫之BeautifulSoup 使用select方法详解
2017/10/23 Python
python实现最大子序和(分治+动态规划)
2019/07/05 Python
Python实现CAN报文转换工具教程
2020/05/05 Python
美国玩具公司:U.S.Toy
2018/05/19 全球购物
印度手工编织服装和家居用品商店:Fabindi
2019/10/07 全球购物
《一株紫丁香》教学反思
2014/02/19 职场文书
大学生求职信范文
2014/05/24 职场文书
实现中国梦思想汇报2014
2014/09/13 职场文书
2015年世界粮食日演讲稿
2015/03/20 职场文书
2015年酒店销售部工作总结
2015/07/24 职场文书
2015毕业设计工作总结
2015/07/24 职场文书
干货:我将这样书写我的演讲稿!
2019/05/09 职场文书
创业计划书之溜冰场
2019/10/25 职场文书
进阶篇之linux环境下安装MySQL数据库
2022/04/09 MySQL
详解Anyscript开发指南绕过typescript类型检查
2022/09/23 Javascript