Skip to main content

概觀

Laravel 的 Queue 功能提供了 Unique(去重)Debounce 兩種 Job 執行控制。皆是為了「當同一 Job 被多次 dispatch 時,省去無謂執行」的機制,但運作有所不同。
Unique Jobs 與 Debounced Jobs 為互斥。請勿於使用 DebounceFor attribute 的 Job 中實作 ShouldBeUnique

Unique Jobs — ShouldBeUnique

當同一 Job 存在於 Queue 期間,將忽略追加的 dispatch。
UpdateSearchIndex 已在 Queue 中(或正在處理),再次 dispatch 同一 Job 會被忽略。

以 key 限縮唯一性約束 — UniqueFor + uniqueId()

若相同 Job 類別下希望將「商品 A 的更新」與「商品 B 的更新」視為不同 Job,可使用 uniqueId() 方法定義 key。
  • uniqueId() 回傳的值成為 cache lock 的 key。
  • 若指定 #[UniqueFor(秒數)],經過該秒數後 lock 會自動釋放(作為 Job 未被處理時的 fail-safe)。

指定 Cache Driver — uniqueVia()

若希望使用預設 cache driver 以外者,可實作 uniqueVia()
Unique Jobs 需要支援 atomic lock 的 cache driver(redisdatabasememcacheddynamodbfilearray)。

ShouldBeUnique vs ShouldBeUniqueUntilProcessing

ShouldBeUnique 的 lock 會保持至 Job 完成或達到重試上限。這在某些情境下會有問題。 例: Queue 中有 1 件 UpdateSearchIndex(product_id: 42),Worker 開始處理後想立即重新 dispatch 相同 Job。ShouldBeUnique 於處理完成前不會讓第 2 件進入 Queue。 此時可使用 ShouldBeUniqueUntilProcessing。因為 lock 於處理開始前釋放,故當 Worker 取出 Job 的瞬間即可進行下次 dispatch。

比較彙整


Debounced Jobs — #[DebounceFor]

DebounceFor attribute 為 Laravel 13 新增的功能。
當短時間內大量 dispatch 同一 Job 時,只執行最後 dispatch 的 1 件。與 Web 前端的 debounce 為同樣思路。
  • debounceId() 回傳的值辨識 Job(每個 product ID 有獨立的 debounce)。
  • 即便 30 秒內以相同 productId dispatch 10 次,也只執行最後 1 件。

maxWait — 最大等待時間上限

於頻繁更新的資料,debounce 可能持續而使 Job 永遠不執行。可透過 maxWait 設定最大延遲時間。
此例中,自初次 dispatch 起最多 120 秒後必定會執行(即便 30 秒 debounce 持續,也會於 120 秒 timeout)。

指定 Cache Driver — debounceVia()

JobDebounced 事件

被後續 dispatch 覆蓋的 Job 會發出 Illuminate\Queue\Events\JobDebounced 事件後從 Queue 中被刪除。透過監聽此事件可以追蹤及監視被 debounce 的 Job。

應該使用哪一個


內部實作

Unique Jobs 的 lock 機制

ShouldBeUnique Job 被 dispatch 時,Laravel 內部會取得 cache 的 Atomic Lock。lock key 格式如下:
若未能取得 lock(已被其他 Job 持有),Job 便不會加入 Queue。

Debounced Jobs 的實作

DebounceFor 內部使用管理「Debounce 視窗」的 cache 項目。每次有新的 dispatch 進來時:
  1. 從 Queue 移除既有 Job(發出 JobDebounced 事件)
  2. 將新 Job 加入 Queue(附帶 Debounce 秒數的延遲)
  3. 重置 cache 的計時器
若有指定 maxWait,也會記錄初次 dispatch 的時間戳記,防止超過該時刻起 maxWait 秒的 Debounce。

參考連結

最後修改於 2026年8月2日