iT邦幫忙

2026 iThome 鐵人賽

DAY 19
0

前言:重試前要不要等待,等多久?

Day 12 講過失敗要局部重試,但沒細講「重試前該等多久」。立刻重試聽起來反應最快,但如果失敗原因是對方暫時過載,立刻重試只會讓對方更喘不過氣,甚至讓所有並行的重試同時湧入,讓情況更糟。

今日目標

  • 認識「立刻重試」在高並行情境下可能造成的問題
  • 比較固定間隔退避跟指數退避兩種策略
  • 理解這個系列素材專案實際用的是哪一種,以及為什麼這個選擇是合理的

固定間隔 vs 指數退避

  • 固定間隔:每次重試前都等待同樣長的時間(例如固定等 10 秒)。實作簡單,但如果失敗原因需要比較長的恢復時間,固定的短間隔可能還沒等到問題解決就又重試一次。
  • 指數退避(exponential backoff):每次重試的等待時間隨失敗次數指數成長(例如 1 秒、2 秒、4 秒、8 秒……),並且通常會加入隨機抖動(jitter)避免大量並行請求在同一時間點集體重試。這種策略在對外部服務發出大量並行請求的情境下更常被使用,因為它能讓重試的時間點自然分散開。

這個系列案例實際用的是固定間隔

tries = 0
while True:
    try:
        await download(segment)
        return
    except Exception as e:
        tries += 1
        if tries >= 10:
            log_failure(segment, e)
            return
        await asyncio.sleep(10)  # 固定等 10 秒

這個選擇談不上完美,但在這個情境下是合理的:片段下載的並行數量本身就被 ThreadPoolExecutor 的 max_workers 限制在一個不大的數字(前面提過是 10),不太會出現「數千個請求同時重試、集體打垮對方」這種需要指數退避加抖動才能緩解的場景。策略選得對不對,要看情境的並行規模,不是有沒有用上聽起來比較講究的演算法。

什麼時候指數退避才真的必要

如果情境換成「面對一個公開 API、有明確的速率限制、大量使用者共用同一個服務」,固定間隔重試就容易出問題——所有失敗的請求都在同一個時間點集體重試,反而製造出一波新的尖峰負載。這種情境下,指數退避加上隨機抖動能有效把重試的時間點打散,避免形成新的尖峰。

今日思考題

你的專案裡的重試邏輯用的是固定間隔還是指數退避?這個選擇是刻意評估過並行規模跟情境需求做的,還是照著某個範例程式碼直接抄過來的?

今日重點回顧

  • 立刻重試在高並行情境下可能讓對方更喘不過氣,甚至集體重試造成新的尖峰負載
  • 固定間隔實作簡單,指數退避加抖動更適合高並行、對外部服務有速率限制的情境
  • 策略選得對不對取決於情境的並行規模,不是選了比較講究的演算法就一定更好

明日預告

明天講合併前的驗證:怎麼先確認片段真的湊齊了,再開始合併。


上一篇
Day 18:下載進度怎麼設計才不會變成一堆散落的 print
下一篇
Day 20:合併片段前,先確認片段真的湊齊了
系列文
下載器不是寫完就能跑:一個 HLS 分段式串流工具的架構與測試修練 共 21 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言