重試策略指的是:針對排程任務失敗後,明訂該不該重試、重試幾次、每次間隔多久的一套固定規則。它處理的是失敗發生後的第一層反應,回答「這次失敗要不要再試一次」,跟 fallback instruction(備援指示)不是同一件事——fallback instruction 處理的是重試策略用盡之後或判定不該重試時該怎麼收尾,兩者是同一套失敗處理流程裡先後接續的兩個階段,重試策略決定要不要再試,備援指示決定試到最後還是不行時怎麼辦。沒有重試策略的排程任務,遇到任何失敗只能做兩種極端反應:立即通知人(把暫時性小問題也當成大事),或完全不通知(讓真正的問題被淹沒在沉默裡)。
這個機制會被需要,是因為排程任務沒有人在旁邊即時判斷「這次失敗嚴不嚴重」,只能照寫死的邏輯反應,而失敗本身有兩種完全不同的性質——伺服器逾時、網路瞬斷這類暫時性問題,通常等一下再做同一件事就會自己好;認證過期、格式錯誤這類結構性問題,不管重試幾次結果都一樣。如果沒有重試策略,系統只能對這兩種性質完全不同的失敗做出同一種反應,要嘛把暫時性問題當成需要人立即處理的大事,長期下來讓值班的人對通知逐漸麻木;要嘛完全不重試也不通知,讓真正該處理的結構性問題被悄悄忽略。重試策略存在的理由,就是先給暫時性問題一個自己恢復的機會,同時設下一個有限的次數,避免無止盡空等。
實務上分三個決定。第一,決定哪些錯誤類型屬於可重試的:逾時、連線中斷、對方回傳 5xx 系列的伺服器錯誤,通常歸為可重試;認證失敗、對方回傳 4xx 系列的請求錯誤、資料驗證失敗,通常歸為不可重試,重試策略只該套用在前者。第二,決定重試間隔怎麼遞增:常見做法是指數退避,第一次等 1 分鐘、第二次等 5 分鐘、第三次等 15 分鐘,讓等待時間隨失敗次數拉長,給暫時性問題愈來愈多自己恢復的空間,而不是每次都用同樣短的間隔硬敲。第三,決定最大重試次數:通常設 3 次,三次都失敗才升級交給 fallback instruction 處理,次數設太少(1 次)等於沒給暫時性問題足夠恢復時間,設太多(10 次以上)則會拖長真正該被人知道的時間點。三個決定合起來,就是一份完整的重試策略。
對你來說,重試策略真正改變的是「值班的人半夜要不要被吵醒」這件事從臨場判斷變成事先訂好的規則。沒有重試策略時,每次失敗都要有人當場決定「這個要不要緊」,判斷標準會因為當下的人、當下的疲憊程度而忽鬆忽緊;有重試策略之後,這個判斷交給固定邏輯自動處理,暫時性問題有機會在通知任何人之前自己好轉,真正該被知道的結構性問題也不會被拖延。要留意的是:重試策略只回答「要不要再試一次」,不回答「試到最後還是不行時該怎麼辦」,如果重試策略用盡後沒有搭配 fallback instruction 明確通知,系統會靜默停擺,看起來一切正常,實際上任務已經放棄,這個空白比完全沒有重試策略更危險,因為錯覺會讓人以為系統仍在正常運作。
AWS 在其官方架構最佳實踐文件中,將指數退避(exponential backoff)列為處理暫時性 API 失敗的建議做法,並說明搭配隨機抖動(jitter,在等待時間裡加入小幅隨機變化)能避免大量請求在同一時間點集中重試、造成新一波過載;這個機制原本針對雲端服務的 API 呼叫設計,但背後「重試間隔隨失敗次數遞增、設有次數上限」的邏輯,同樣適用於排程任務失敗後的重試策略設計。
優點是把「這次失敗要不要緊」的判斷從臨場反應變成固定邏輯,減少不必要的通知雜訊,也給暫時性問題自己恢復的空間;缺點是重試本身會拖延真正該被人知道的時間點,重試次數設太多會讓結構性問題被延遲發現,而且重試策略本身不負責通知,必須搭配 fallback instruction 才是完整的失敗處理,單獨使用重試策略無法確保系統不會靜默失敗。