pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

源碼分析 Laravel 重復執行同一個隊列任務的原因

laravel 的隊列服務對各種不同的后臺隊列服務提供了統一的 API,下面這篇文章通過源碼分析給大家介紹了關于 Laravel 重復執行同一個隊列任務的原因,文中通過示例代碼介紹的非常詳細

前言

laravel 的隊列服務對各種不同的后臺隊列服務提供了統一的 API。隊列允許你延遲執行消耗時間的任務,比如發送一封郵件。這樣可以有效的降低請求響應的時間。

發現問題

在 Laravel 中使用 Redis 處理隊列任務,框架提供的功能非常強大,但是最近遇到一個問題,就是發現一個任務被多次執行,這是為什么呢?

先說原因:

因為在 Laravel 中如果一個隊列(任務)執行時間大于 60 秒,就會被認為執行失敗并重新加入隊列中,這樣就會導致重復執行同一個任務。

這個任務的邏輯就是給用戶推送內容,需要根據隊列內容取出用戶并遍歷,通過請求后端 HTTP 接口發送。比如有 10000 個用戶,在用戶數量多或接口處理速度沒那么快的情況下,執行時間肯定會大于 60 秒,于是這個任務就被重新加入隊列。情況更糟糕一點,前面的任務如果都沒有在 60 秒執行完,就都會重新加入隊列,這樣同一個任務就不止重復執行一次了,而是多次。

下面從 Laravel 源代碼找一下罪魁禍首。

源代碼文件:vendor/laravel/framework/src/Illuminate/Queue/RedisQueue.php


/**
 * The expiration time of a job.
 *
 * @var int|null
 */
protected $expire = 60;

這個 $expire 成員變量是一個固定的值,Laravel 認為一個隊列再怎么 60 秒也該執行完了吧。取隊列方法:


public function pop($queue = null)
{
 $original = $queue ?: $this->default; 
 $queue = $this->getQueue($queue); 
 $this->migrateExpiredJobs($queue.':delayed', $queue); 
 if (! is_null($this->expire)) {
  $this->migrateExpiredJobs($queue.':reserved', $queue);
 } 
 list($job, $reserved) = $this->getConnection()->eval(
  LuaScripts::pop(), 2, $queue, $queue.':reserved', $this->getTime() + $this->expire
 ); 
 if ($reserved) {
  return new RedisJob($this->container, $this, $job, $reserved, $original);
 }
}

取隊列有幾步操作,因為隊列執行失敗,或執行超時等都會放入另外的集合保存起來,以便重試,過程如下:

    1.把因執行失敗的隊列從 delayed 集合重新 rpush 到當前執行的隊列中。

    2.把因執行超時的隊列從 reserved 集合重新 rpush 到當前執行的隊列中。

    3.然后才是從隊列中取任務開始執行,同時把隊列放入 reserved 的有序集合。

這里使用了 eval 命令執行這個過程,用到了幾個 lua 腳本。

從要執行的隊列中取任務:


local job = redis.call('lpop', KEYS[1])
local reserved = false
if(job ~= false) then
 reserved = cjson.decode(job)
 reserved['attempts'] = reserved['attempts'] + 1
 reserved = cjson.encode(reserved)
 redis.call('zadd', KEYS[2], ARGV[1], reserved)
end
return {job, reserved}

可以看到 Laravel 在取 Redis 要執行的隊列的時候,同時會放一份到一個有序集合中,并使用過期時間戳作為分值。

只有當這個任務完成后,再把有序集合中這個任務移除。從這個有序集合移除隊列的代碼就省略,我們看一下 Laravel 如何處理執行時間大于 60 秒的隊列。

也就是這段 lua 腳本執行的操作:


local val = redis.call('zrangebyscore', KEYS[1], '-inf', ARGV[1])
if(next(val) ~= nil) then
 redis.call('zremrangebyrank', KEYS[1], 0, #val - 1)
 for i = 1, #val, 100 do
  redis.call('rpush', KEYS[2], unpack(val, i, math.min(i+99, #val)))
 end
end
return true

這里 zrangebyscore 找出分值從無限小到當前時間戳的元素,也就是 60 秒之前加入到集合的任務,然后通過 zremrangebyrank 從集合移除這些元素并 rpush 到隊列中。

看到這里應該就恍然大悟了。

如果一個隊列 60 秒沒執行完,那么進程在取隊列的時候從 reserved 集合中把這些任務又重新 rpush 到隊列中。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對編程學習網的支持。

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

Gravatar是一圖像跟隨著您到訪過的網站,當您在博客中留言或發表文章,它將會出現在您的名稱旁。下面這篇文章主要給大家介紹了關于利用Laravel如何生成 Gravatar 頭像地址的優雅方法,
Laravel隊列服務為各種不同的后臺隊列提供統一的API,下面這篇文章主要給大家介紹了關于Laravel中使用Queue的最基本操作教程,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借
這篇文章主要給大家介紹了關于 Laravel Redis 多個進程同時取隊列問題的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或工作具有一定的參考學習價值,需要的朋友下面來
最近在使用laravel5.5,利用其實現了一個功能,下面分享給大家,這篇文章主要給大家介紹了關于Laravel 5.5基于內置的Auth模塊如何實現前后臺登陸的相關資料,文中通過示例代碼介紹的非
主站蜘蛛池模板: 九爱图纸|机械CAD图纸下载交流中心| 工控机-图像采集卡-PoE网卡-人工智能-工业主板-深圳朗锐智科 | 工业胀紧套_万向节联轴器_链条-规格齐全-型号选购-非标订做-厂家批发价格-上海乙谛精密机械有限公司 | 台湾HIWIN上银直线模组|导轨滑块|TBI滚珠丝杆丝杠-深圳汉工 | 轴流风机-鼓风机-离心风机-散热风扇-罩极电机,生产厂家-首肯电子 | 石家庄装修设计_室内家装设计_别墅装饰装修公司-石家庄金舍装饰官网 | 合肥仿石砖_合肥pc砖厂家_合肥PC仿石砖_安徽旭坤建材有限公司 | 新型锤式破碎机_新型圆锥式_新型颚式破碎机_反击式打沙机_锤式制砂机_青州建源机械 | 磁力抛光研磨机_超声波清洗机厂家_去毛刺设备-中锐达数控 | 云南标线|昆明划线|道路标线|交通标线-就选云南云路施工公司-云南云路科技有限公司 | 氧氮氢联合测定仪-联测仪-氧氮氢元素分析仪-江苏品彦光电 | 东莞市超赞电子科技有限公司 全系列直插/贴片铝电解电容,电解电容,电容器 | 汽车水泵_汽车水泵厂家-瑞安市骏迪汽车配件有限公司 | 安全,主动,被动,柔性,山体滑坡,sns,钢丝绳,边坡,防护网,护栏网,围栏,栏杆,栅栏,厂家 - 护栏网防护网生产厂家 | 置顶式搅拌器-优莱博化学防爆冰箱-磁驱搅拌器-天津市布鲁克科技有限公司 | 世界箱包品牌十大排名,女包小众轻奢品牌推荐200元左右,男包十大奢侈品牌排行榜双肩,学生拉杆箱什么品牌好质量好 - Gouwu3.com | 润滑脂-高温润滑脂-轴承润滑脂-食品级润滑油-索科润滑油脂厂家 | 吲哚菁绿衍生物-酶底物法大肠菌群检测试剂-北京和信同通科技发展有限公司 | 吸污车_吸粪车_抽粪车_电动三轮吸粪车_真空吸污车_高压清洗吸污车-远大汽车制造有限公司 | 升降炉_真空气氛炉_管式电阻炉厂家-山东中辰电炉有限公司 | 密集架-手摇-智能-移动-价格_内蒙古档案密集架生产厂家 | 京港视通报道-质量走进大江南北-京港视通传媒[北京]有限公司 | 压装机-卧式轴承轮轴数控伺服压装机厂家[铭泽机械] | 【ph计】|在线ph计|工业ph计|ph计厂家|ph计价格|酸度计生产厂家_武汉吉尔德科技有限公司 | DAIKIN电磁阀-意大利ATOS电磁阀-上海乾拓贸易有限公司 | 重庆磨床过滤机,重庆纸带过滤机,机床伸缩钣金,重庆机床钣金护罩-重庆达鸿兴精密机械制造有限公司 | 汽车整车综合环境舱_军标砂尘_盐雾试验室试验箱-无锡苏南试验设备有限公司 | 塑木弯曲试验机_铜带拉伸强度试验机_拉压力测试台-倾技百科 | 洛阳防爆合格证办理-洛阳防爆认证机构-洛阳申请国家防爆合格证-洛阳本安防爆认证代办-洛阳沪南抚防爆电气技术服务有限公司 | 团建-拓展-拓展培训-拓展训练-户外拓展训练基地[无锡劲途] | 除尘器布袋骨架,除尘器滤袋,除尘器骨架,电磁脉冲阀膜片,卸灰阀,螺旋输送机-泊头市天润环保机械设备有限公司 | 硬质合金模具_硬质合金非标定制_硬面加工「生产厂家」-西迪技术股份有限公司 | 船用烟火信号弹-CCS防汛救生圈-船用救生抛绳器(海威救生设备) | 防渗膜厂家|养殖防渗膜|水产养殖防渗膜-泰安佳路通工程材料有限公司 | 品牌策划-品牌设计-济南之式传媒广告有限公司官网-提供品牌整合丨影视创意丨公关活动丨数字营销丨自媒体运营丨数字营销 | 浙江寺庙设计-杭州寺院设计-宁波寺庙规划_汉匠 | 高速混合机_锂电混合机_VC高效混合机-无锡鑫海干燥粉体设备有限公司 | 密封圈_泛塞封_格莱圈-[东莞市国昊密封圈科技有限公司]专注密封圈定制生产厂家 | 山东商品混凝土搅拌楼-环保型搅拌站-拌合站-分体仓-搅拌机厂家-天宇 | 螺旋叶片_螺旋叶片成型机_绞龙叶片_莱州源泽机械制造有限公司 | 艾默生变频器,艾默生ct,变频器,ct驱动器,广州艾默生变频器,供水专用变频器,风机变频器,电梯变频器,艾默生变频器代理-广州市盟雄贸易有限公司官方网站-艾默生变频器应用解决方案服务商 |