Laravel是如何防止你的計時任務重複執行的
基本介紹
有時候一個定時任務執行需要的時間可能會比我們想像的要長,這就會引起一個問題—當前任務還沒執行完畢的時候另一個相同的任務也會執行,導致任務重複。 例如想像一下我們執行每分鐘產生一次報告的任務,在經過一段時間後,資料量變得很大導致執行時間多於1分鐘,這樣就會導致在上一個任務還沒結束的時候另一個相同的任務開始執行。
解決方法
大部分情況下是沒有什麼問題的,但是有時我們需要避免這種情況來保證獲得正確的資料。在Laravel中我們可以透過withoutOverlapping
方法來處理:
$schedule->command('mail:send')->withoutOverlapping();
Laravel會檢查Console\Scheduling\Event::withoutOverlapping
屬性,如果該值為true那麼將會針對這個任務建立一個互斥鎖(mutex),並且只有在可以建立互斥鎖的情況下才會執行此任務。
什麼是互斥鎖?
這是我在網路上找到的最有趣的解釋:
當我們在開會進行激烈的討論時,我會從我桌子裡拿出來一個尖叫雞。只有手裡拿著尖叫雞的人才能說話,如果你沒有拿著尖叫雞你是不能說話的。你只能向會議主持人請示,只有在你拿到尖叫雞的時候你才能說話否則只能等待。當你講話完畢的時候,將尖叫雞還給會議主持人,主持人會將尖叫雞給到下一個讓其說話。這樣會確保人們不會互相交談,同時他們也會有自己的時間來進行演講。
將尖叫雞換成互斥鎖,人換成線程。你基本上就有了一個互斥鎖的基本概念。
-- https://stackoverflow.com/questions/34524/...
原理分析
Laravel在第一次執行任務的時候會建立一個互斥鎖,然後在每次執行任務時會檢查互斥鎖是否存在,只有互斥鎖不存在的時候任務才會執行。以下是withoutOverlapping
方法:
public function withoutOverlapping() { $this->withoutOverlapping = true; return $this->then(function () { $this->mutex->forget($this); })->skip(function () { return $this->mutex->exists($this); }); }
Laravel建立了一個過濾回呼方法來告訴計畫管理器忽略互斥鎖仍然存在的任務,同時也建立了一個在完成任務實例後清除互斥鎖的回調。同時,在執行任務之前,Lravel會在Console\Scheduling\Event::run()
方法中依序執行下面一系列的檢查:
if ($this->withoutOverlapping && ! $this->mutex->create($this)) { return; }
那麼互斥鎖的屬性是從哪裡來的呢?
當Console\Scheduling\Schedule
被實例化的時候,Laravel會檢查Console\Scheduling\Mutex
是否綁定到了容器,如果是那麼就會實例化它,否則會使用Console\Scheduling\CacheMutex
$this->mutex = $container->bound(Mutex::class) ? $container->make(Mutex::class) : $container->make(CacheMutex::class);
現在當任務管理器在註冊事件的時候會將互斥鎖的實例一併傳進去:
$this->events[] = new Event($this->mutex, $command);
Laravel預設使用了快取實現的互斥鎖,但你可以自己實作並替換它。
快取版的互斥鎖
CacheMutex類別只有3個簡單的方法,它使用了事件互斥鎖的名字作為快取的鍵值:
public function create(Event $event) { return $this->cache->add($event->mutexName(), true, 1440); } public function exists(Event $event) { return $this->cache->has($event->mutexName()); } public function forget(Event $event) { $this->cache->forget($event->mutexName()); }
就就像我們之前看過的,管理器註冊了一個執行後回調來保證任務執行完畢的時候移除互斥鎖,對於一個系統裡的命令來說也許已經可以確保移除了。但是對於一個回呼方法的任務來說腳本可能在執行回調的時候結束,因此為了避免這種情況在Console\Scheduling\CallbackEvent::run()
方法中加入了下面的程式碼確保互斥鎖在任務意外關閉的時候能夠正常移除:
register_shutdown_function(function () { $this->removeMutex(); });
更多Laravel相關技術文章,請訪問Laravel教程專欄進行學習!
以上是Laravel是如何防止你的計時任務重複執行的的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undress AI Tool
免費脫衣圖片

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Stock Market GPT
人工智慧支援投資研究,做出更明智的決策

Clothoff.io
AI脫衣器

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

創建referrals表記錄推薦關係,包含推薦人、被推薦人、推薦碼及使用時間;2.在User模型中定義belongsToMany和hasMany關係以管理推薦數據;3.用戶註冊時生成唯一推薦碼(可通過模型事件實現);4.註冊時通過查詢參數捕獲推薦碼,驗證後建立推薦關係並防止自薦;5.當被推薦用戶完成指定行為(如下單)時觸發獎勵機制;6.生成可分享的推薦鏈接,可使用Laravel簽名URL增強安全性;7.在儀表板展示推薦統計信息,如總推薦數和已轉化數;必須確保數據庫約束、會話或Cookie持久化、

conscortorSandMutatorsInlaravel'SeloquentormallowyOutoFormAtormanIpulateModeModeLattributesWhenRetRievorvingOrstTingValues.1.useaccessorstocustomizeattributeretributeretrieval,sueascaScapapitalizingfirst_namevirst_nameviagetFirstnameAtTeameAtTeameAtTeameAtTeameAtTeameAttribute($ value)($ value)

Repository模式是一種設計模式,用於解耦業務邏輯與數據訪問邏輯。 1.它通過接口(Contract)定義數據訪問方法;2.具體操作由Repository類實現;3.控制器通過依賴注入使用接口,不直接接觸數據源;4.優勢包括代碼整潔、可測試性強、便於維護和團隊協作;5.適用於中大型項目,小型項目可直接使用模型。

laravelleloquentsuportsubqueriesInSelect,從哪裡,andorderbyClauses啟用Feflexibledataretievalwithoutrawsql; 1.UseselectSub()toaddcompentedColumnSlumnsLikePostCountCountCountCountCountPeruser; 2.Usefromsub; 2.usefromsub; 2.Usefromsub orclosolusoblesoblesoboledInfom()

laravelimplementsthemvcpatternbyingmodelsmodelsfordatamanage,ControllerSforBusinessLogic,andViewSforPresentation.1)模型InnlaravelaravelAravelAravelAravelAravelAravelAravelAraveRormshandlingDataAndRealations.2)ControllersManagetheflowbetneflowbetefbetefbetnefbetnemodelsandviews.3)

Laravel'simplementationofMVChaslimitations:1)Controllersoftenhandlemorethanjustdecidingwhichmodelandviewtouse,leadingto'fat'controllers.2)Eloquentmodelscantakeontoomanyresponsibilitiesbeyonddatarepresentation.3)Viewsaretightlycoupledwithcontrollers,m

創建Laravel項目並配置數據庫環境;2.使用Artisan生成模型、遷移和控制器;3.在api.php中定義API資源路由;4.實現控制器中的增刪改查方法並使用請求驗證;5.安裝LaravelSanctum實現API認證並保護路由;6.統一JSON響應格式並處理錯誤;7.使用Postman等工具測試API,最終得到一個功能完整、可擴展的RESTfulAPI。

InstallLaravelCashierviaComposerandconfiguremigrationandBillabletrait.2.CreatesubscriptionplansinStripeDashboardandnoteplanIDs.3.CollectpaymentmethodusingStripeCheckoutandstoreitviasetupintent.4.SubscribeusertoaplanusingnewSubscription()anddefaultpay
