具代表性的面試主題

後端面試:如何設計具備安全重播的死信佇列處理流程?

後端困難
OfferCC 編輯團隊發佈 更新

題幹

請設計一個訊息處理系統:失敗訊息進入死信佇列,修復問題後可以安全重播。你如何保證不丟訊息、不重複副作用,並避免重播再次拖垮系統?

題幹與適用場景

設計一個非同步訊息流程:訊息經過有限次重試後進入死信佇列(DLQ),營運人員修復根因後可以按條件重播。說明訊息如何進入 DLQ、如何調查、如何選擇批次、如何避免重複副作用,以及如何保護正常流量。

這道題適用於後端、平台、基礎設施和資料工程職位。Amazon 的軟體開發面試主題強調運用技術解決問題,而不是背誦細節。AWS 文件說明 DLQ 用於隔離未成功消費的訊息,並應配合告警和重試次數;Google Pub/Sub 文件提供死信主題與 replay/seek 語義。重點是故障邊界和營運閉環。

面試官考察點

  • 區分暫時性錯誤、毒丸訊息、業務拒絕和過期訊息。
  • DLQ 是否保存版本、租戶、分區、追蹤 ID 和失敗原因。
  • 重播是否具備冪等鍵、範圍、速率限制、審批和停止條件。
  • 是否明確順序、保留期、重複投遞和至少一次語義。
  • 是否用指標驗證恢復,而不是只說“重新放回主佇列”。

回答前需要釐清的問題

  • 投遞語義是至少一次、至多一次,還是業務上要求有效一次?
  • 哪些失敗可以重試,哪些必須人工處理或丟棄?
  • 訊息保留多久?過期訊息還有價值嗎?
  • 同一聚合鍵是否必須有序?
  • 消費者副作用是否支援冪等或去重?
  • 誰可以查看、重播和刪除訊息,是否需要審計?
  • 正常流量 SLO、佇列容量和重播容量是多少?
  • 重播失敗後進入同一 DLQ 還是獨立 replay-DLQ?

30 秒回答框架

“我先定義至少一次投遞、保留期和順序鍵。消費者對可重試錯誤使用有上限的退避,對毒丸或業務拒絕記錄原因後轉入 DLQ。DLQ 保存原始訊息、嘗試次數、消費者版本和追蹤 ID。修復後按租戶、版本或時間窗建立重播批次,先隔離驗證,再限速投遞;消費者用冪等鍵保護副作用。監控 DLQ 深度、最老訊息、重播失敗率和重複率,超過閾值就暫停。”

分步驟深入解答

步驟一:定義失敗狀態機

正常佇列、重試、DLQ、人工修復和 replay-DLQ 應是可區分狀態。不可重試的業務拒絕不能無限重試。

步驟二:設計訊息元資料

保存事件 ID、業務冪等鍵、產生時間、租戶或分區、模式版本、嘗試次數、原始追蹤 ID 和錯誤分類。原始載荷不可變,重播只改變投遞元資料。

步驟三:確定重試與入 DLQ 規則

設置最大接收次數、退避上限和保留期。AWS SQS 文件指出 DLQ 有源佇列和區域約束,並應配置告警。過期或撤銷訊息應記錄原因後人工處置。

步驟四:設計安全重播流程

重播請求包含篩選條件、目標版本、速率上限、最大批量、審批人和過期時間。先抽樣驗證,再分批投遞;重播佇列與正常佇列隔離。

控制點目的失敗動作
冪等鍵防止重複副作用拒絕或返回已處理結果
速率上限保護消費者和下游暫停重播
批次範圍限制影響面縮小篩選條件
審批與審計追蹤責任阻止未授權操作
replay-DLQ隔離再次失敗生成新診斷批次

步驟五:處理順序與並發

需要有序時按聚合鍵分組,避免同鍵的正常消費與重播並行。不要聲稱佇列天然提供端到端 exactly-once。

步驟六:保護副作用

消費者以事件 ID 或業務冪等鍵做條件寫。支付、郵件等不可回滾副作用需要冪等請求鍵和結果查詢;重播工具不能假設刪除訊息就足夠。

步驟七:可觀測和營運閉環

監控 DLQ 深度、最老訊息年齡、錯誤分類比例、重播吞吐、失敗率、重複副作用和下游延遲。每個批次記錄操作者、原因、時間、結果和停止記錄。

步驟八:容量、兼容和停止

估算最大重播速率,保證新消費者兼容舊模式。根因未修復、下游過載或重複率上升時立即暫停,保留原始證據。

高品質示範回答

“我設計的是至少一次投遞的訂單事件流程。網路超時最多重試 5 次並退避;模式錯誤、權限拒絕和過期事件進入 DLQ。每條訊息保存事件 ID、訂單 ID、租戶、模式版本、首次入隊時間、嘗試次數、錯誤分類和 trace ID,原始載荷不可變。

修復消費者後,營運人員建立批次,指定租戶、時間範圍、目標版本、每秒上限、審批人和過期時間。先抽取 50 條在隔離消費者上驗證,再以正常流量 10% 的速率投遞。訂單狀態表以事件 ID 做冪等條件寫,支付呼叫使用同一業務冪等鍵。相同訂單的正常訊息和重播訊息不能並行。

告警覆蓋最老訊息、重播失敗率、重複寫入和下游延遲;任何閾值觸發都暫停批次並把再次失敗的訊息放入 replay-DLQ。批次記錄篩選、版本、操作者、結果和停止原因。”

常見錯誤

  • 把 DLQ 當垃圾桶,不保留錯誤分類和原始證據。
  • 無限重試毒丸訊息,持續阻塞正常流量。
  • 只說“放回主佇列”,沒有批次、審批和速率控制。
  • 假設佇列提供端到端 exactly-once。
  • 沒有冪等鍵,重播造成重複扣款、發信或狀態推進。
  • 忽略順序鍵,導致舊事件覆蓋新狀態。
  • 只監控佇列長度,不監控最老訊息和業務結果。
  • 重播與正常消費共用容量,恢復流量再次過載。

追問及應對

追問一:為什麼不直接增加最大重試次數?

重試適合暫時性故障;毒丸、模式錯誤和永久業務拒絕會浪費容量。次數應結合故障類型、保留期和等待成本決定。

追問二:重播時怎樣保證同一訂單有序?

按訂單鍵分區,阻止同鍵並行,並在正常消費和重播之間建立互斥;若允許無序,要說明狀態轉換如何防止舊事件覆蓋新狀態。

追問三:下游沒有冪等介面怎麼辦?

建立本地去重和結果查詢;對不可逆副作用改為人工核對、補償流程或供應商支援的冪等機制。

追問四:重播再次失敗怎麼辦?

進入獨立 replay-DLQ,保留原批次和新錯誤資訊,暫停相關篩選條件並通知負責人。

追問五:如何估算重播速率?

根據消費者能力、下游配額、正常流量餘量和恢復時間設定上限,先小批量壓測,再逐步提高。

追問六:什麼時候應該丟棄訊息?

只有業務明確判定訊息過期、撤銷或無價值,並完成審計和責任確認後丟棄;保留摘要和原因。

公開來源

同類題目