消息中心 - Laravel的Redis隊列(一)


前言


Laravel的隊列可以用在輕量級的隊列需求中。比如我們系統中的短信、郵件等功能,這些功能有一些普遍的特征,異步、重試、並發控制等。Laravel現在主要支持的隊列服務有Null、Sync、Database、Redis、Beanstalkd、Sqs。
在我們的項目中(消息中心、人事)用的主要是redis,接下來我會介紹下隊列基於redis驅動的運行機制。

背景知識


Laravel啟動后,加載config/app.php的providers數組中的服務提供者 QueueServiceProvider,在隊列服務提供者中,已經注冊了一系列相關服務。
6

在.env配置文件中,我們設置了QUEUE_DRIVER為redis,系統啟動后會自動生成Redis連接,同時注冊了Work消費者,隊列監聽器以及錯誤服務。在queue.php和database.php配置中都默認了相關的redis設置。

任務調度


調度如下:
7

laravel 的隊列服務由兩個進程控制,一個是事件生產者(黑線),一個是事件消費者(黃線)。
有三個隊列,主隊列 queues:default(下面default代替),延時隊列 queues:default:delayed(下面delayed代替),待處理隊列 queues:default:reserved(下面reserved代替)。所有的隊列事件都由事件消費者去消費主隊列中的事件。(隊列名稱default在queue.php中被定義)

1. 事件觸發:dispatch(new Event());

事件觸發后,dispatch判斷Event是否繼承隊列類,是,將事件分發到隊列執行流程中。隊列執行流程會根據Event的延時屬性判斷,否,將Event放到即時處理queues:default 隊列中,是,將Event放入延時 queues:default:delayed 隊列中。

2. 消費:php artisan queue:work

圖中A、B、C、D為消費者進程依次執行步驟,淡黃色背景的代碼備注都為對隊列的操作命令(predis 實現redis api),每個備注里面對事件的操作要么一起成功,要么一起失敗(Lua腳本)。

3. A: 對delayed、default隊列操作

A1:取出小於當前時間的(時間戳)所有Event,賦給val,刪除delayed隊列中0到val.length長度的Event(redis的有序集合有一個分數,有序集合根據這個分數從小到大排序,這里的時間戳就是分數)。
A2:將上面獲取的Event,放入到主隊列 default。

4. B: 對reserved、default隊列操作

B1:取出小於當前時間的所有Event,賦給val,刪除reserved隊列中0到val長度的Event。
B2:將上面獲取的Event,放入到主隊列 default。

5. C: 對default、reserved隊列操作

C1:取出主隊列中的所有Event。
C2:將Event放入reserved,且記錄Event的執行次數(保留Event,由D執行后,根據Event執行結果處理這些Event)。

6. D: 處理Event(由C步驟得到的Event,交給D)

根據得到的Event依次執行(也就是通知監聽這個Event的所有監聽者),同時刪除reserved隊列的相對應的Event(無論執行失敗還是成功),如果執行失敗會將任務放入reserved隊列中,執行時間為1540097000(1540096910 + 90,90為設置的延時時間),以便下次執行。

結尾


以上就是Laravel隊列所有的執行流程,當然里面包括執行失敗的錯誤處理、如何通知監聽者等細節都沒講,大家可以自行分析代碼理解。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM