浅谈Laravel队列实现原理解决问题记录
2017-08-19 20:10
891 查看
问题
公司项目使用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
最后
遇到问题,莫要病急乱投医。从代码入手,分析理解实现原理,找对点,解决方法也许很简单,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
相关文章推荐
- 浅谈java阻塞队列实现原理
- ginx+php-fpm实现原理及问题记录
- 浅谈个人在瀑布流网页的实现中遇到的问题和解决方法
- [问题记录.dotnet]解决“此实现不是 Windows 平台 FIPS 验证的加密算法的一部分”
- 混合app开发:自己实现的页面历史记录管理模块,解决页面"回退难"的问题
- Spring Session解决分布式Session问题的实现原理
- 基于堆实现的优先级队列:PriorityQueue 解决 Top K 问题
- 实战解决问题开发出功能固然重要--->基本功锤炼和技术的实现原理,也非常重要
- 优先队列PriorityQueue实现 大小根堆 解决top k 问题
- Spring Session解决分布式Session问题的实现原理
- 一个JS图片放大镜,实现动态记录的图片放大,避免内存泄露,解决IE6下无法遮盖select控件问题
- 图层控制界面实现记录-单图层控制实现和事件路由问题解决
- laravel 解决leftjoin带条件查询没有返回右表为NULL的记录问题
- Spring Session解决分布式Session问题的实现原理
- Spring Session解决分布式Session问题的实现原理
- 基于堆实现的优先级队列:PriorityQueue 解决 Top K 问题
- Spring Session解决分布式Session问题的实现原理
- 优先队列实现 大小根堆 解决top k 问题
- SDWebImage的原理。实现机制。如何解决TableView卡的问题。
- CAS操作实现并发的优势、以及实现一个无锁队列、怎样解决ABA 问题