洞察自動化約 4 分鐘閱讀

排程重疊時,如何避免同一工作重複執行

排程器準時觸發,不代表上一輪工作已經完成。真正可靠的設計,必須先定義重疊時的業務語意,再以互斥、冪等與可觀測性共同守住資料一致性。

先定義重疊時應該發生什麼事

排程重疊通常不是排程器本身的錯,而是工作執行時間超過觸發間隔,或前一輪因外部 API、資料庫鎖定、網路重試而延遲。另一種常見情況是服務部署了多個實例,每個實例都收到相同的排程事件。工程團隊首先要確認的,不是「要用哪一種鎖」,而是同一工作重疊時應採取什麼業務行為。

常見語意包括:忽略新的觸發、等待前一輪完成、將新工作排入佇列,或取消舊工作並以最新資料重跑。定期彙整歷史交易通常適合等待或排隊;只產生最新快照的工作可能適合略過中間執行;涉及通知、扣款或建立訂單的工作,則不能只靠跳過策略,還必須保證每個業務事件不會被處理兩次。

鎖定避免的是同時執行,冪等避免的是重複產生結果。兩者處理的風險不同。即使系統已經使用分散式鎖,工作仍可能在完成後、回報成功前中斷,導致排程器重新派送。因此,重要副作用仍需具備冪等保護。

  • 略過:適合只關心最新狀態、允許漏掉單次執行的工作。
  • 等待:適合每一輪都應完成,但可以容忍延遲的批次流程。
  • 合併:適合多次觸發可以收斂成一次計算的同步或快照工作。
  • 逐筆處理:適合不能遺漏的訂單、帳務、通知與整合事件。

把互斥控制放在所有執行者都看得到的位置

如果應用程式只有單一程序,記憶體旗標或程序內 mutex 看似足夠;但只要服務可能水平擴充、重新部署,或由兩個排程來源觸發,這種鎖就失去保護能力。互斥狀態應存放在所有執行者共享且能原子更新的系統,例如主要資料庫、Redis,或本身支援單一消費者與可見性逾時的工作佇列。

選擇鎖定機制時,優先考慮現有基礎設施與故障模式。資料庫條件更新、唯一鍵或 advisory lock 容易與業務資料放在同一個交易邊界,適合中低頻排程。Redis 鎖取得速度快,但必須正確處理租約期限、持有者識別與網路分割。訊息佇列能吸收尖峰並提供重試,卻不會自動讓業務操作冪等,而且可能以至少一次語意重新投遞。

鎖的粒度也會直接影響吞吐量。以固定名稱鎖住整個排程最簡單,但會讓不同租戶、日期或資料分區彼此阻塞。較實用的方式是從工作名稱與業務範圍產生穩定的鎖定鍵,例如工作類型、租戶與結算日期的組合。粒度越細,並行度越高,但鍵值規則與監控也越複雜。

  • 鎖定鍵必須由穩定的業務識別組成,不能依賴程序 ID 或隨機值。
  • 取得鎖必須是原子操作,不能先查詢再寫入,否則仍會產生競爭條件。
  • 只有持有鎖的執行者可以釋放它,避免舊程序刪除新程序取得的鎖。
  • 若使用資料庫唯一鍵防重,應將重複衝突視為預期結果,而不是未知錯誤。

租約逾時不能只靠猜測

永久鎖會在程序崩潰後留下死鎖,因此分散式鎖通常使用有限期限的租約。然而,租約太短會在工作仍執行時失效,讓另一個執行者進場;租約太長則會拖慢故障復原。不要只依平均執行時間設定期限,還要納入資料量波動、外部服務延遲、垃圾回收停頓與部署終止時間。

長時間工作可使用心跳續租,但續租必須驗證持有者識別。更嚴謹的設計會加入單調遞增的 fencing token:每次取得鎖都拿到較新的版本,下游資料寫入只接受最新版本。如此即使舊執行者因網路暫停而在租約失效後恢復,也不能覆蓋新執行者已完成的結果。

無論鎖多可靠,真正的最後防線仍是業務層冪等。為每次邏輯工作建立唯一的執行鍵,並在產生副作用前以唯一約束、狀態轉移條件或 outbox 記錄確認是否已處理。呼叫外部系統時,若對方支援 idempotency key,應傳遞同一個穩定鍵;若不支援,就要在本地保存請求與結果,並設計可對帳的補償流程。

  • 工作開始前記錄執行鍵、鎖定鍵、觸發來源與嘗試次數。
  • 分段處理大量資料,讓重試能從安全的檢查點繼續。
  • 將狀態更新設計成明確轉移,例如只允許從待處理變成處理中。
  • 不要在無法判斷外部請求是否成功時直接重送具破壞性的操作。

讓跳過、重試與卡住都能被看見

防重機制若缺乏觀測,容易把真正的故障偽裝成「正常略過」。每次觸發至少應記錄排程時間、實際開始時間、鎖等待時間、執行鍵、持有者、處理範圍、完成狀態與失敗原因。指標也要區分成功、因重疊而略過、等待逾時、重試成功及永久失敗,否則營運人員只會看到排程仍持續觸發,卻不知道資料是否更新。

告警門檻應依業務新鮮度設定,而不是只看單次失敗。例如,每幾分鐘同步的工作偶爾因上一輪尚未完成而略過,可能完全合理;但如果最後成功時間已超過可接受範圍,就應告警。手動重跑工具也要沿用相同的鎖定鍵與冪等規則,不能成為繞過保護機制的第二條路徑。

上線前可刻意測試兩個執行者同時啟動、鎖持有者中途終止、租約剛好失效、外部 API 已成功但本地尚未記錄,以及重試訊息重複送達等情境。可靠的排程設計不是承諾永遠不重複觸發,而是讓重複觸發可預期、可復原,且不會重複產生業務結果。

本文由 AI 依聖索科技規劃的主題自動撰寫,內容為一般性說明,導入前請依實際情況評估或與我們討論。

開始

有類似的需求?

告訴我們你的產業、目前系統狀態與預算範圍。我們會在 2 個工作天內回覆,並安排 30 分鐘免費諮詢。