題幹與適用場景
這道題考察分散式所有權遷移,而不是記憶某個 Kafka 設定。eager 再平衡會先撤銷全部分割區,cooperative 再平衡允許成員保留不必遷移的分割區,只撤銷需要移動的部分。回答要說明成員版本、assignor 協定、offset 提交、故障窗口與觀測指標。
面試官考察什麼
- 能否解釋 eager 與 cooperative 的撤銷和交接差異。
- 能否設計相容的滾動升級順序,避免新舊成員協商失敗。
- 能否把分割區所有權、offset、處理中的訊息與提交時機對應起來。
- 能否處理崩潰、逾時、重複消費、回滾與容量不足。
回答前需要釐清的問題
確認 Kafka 用戶端版本、目前 assignor 清單、是否啟用靜態成員、單則訊息處理時間、允許的重複消費窗口與 rebalance 延遲預算。也要問清楚訊息是否可冪等處理、下游是否支援去重,以及發布系統能否分階段回滾。最後確認擴縮容峰值、分割區數與監控告警閾值。
30 秒回答框架
先讓所有成員升級到支援 cooperative 協定的版本,但保留相容的 assignor 清單;確認群組協定一致後,再透過滾動發布把 CooperativeStickyAssignor 設為首選並移除舊策略。每次 rebalance 只撤銷需要移動的分割區,消費者在 revoke 回呼中停止拉取並提交已完成 offset,接收者從已提交 offset 繼續。監控 rebalance 次數、撤銷分割區數、處理延遲與重複率;崩潰時依賴 session timeout 與 offset 復原,回滾則恢復舊設定並再次滾動。
分步驟深入解答
1. 定義協定與相容矩陣
Kafka 的 assignor 是群組級協商結果,不能只改一台實例。先把用戶端升級到支援 cooperative 的版本,確保所有實例能解析同一協定;舊成員仍在群組內時,不能讓新成員單方面假設 cooperative。設定示意如下:
partition.assignment.strategy=\
org.apache.kafka.clients.consumer.CooperativeStickyAssignor,\
org.apache.kafka.clients.consumer.RangeAssignor第一階段保留相容項完成滾動升級,第二階段在全組支援後把 cooperative 設為首選並移除舊項。每一階段都要驗證群組實際協定與 assignment 結果,而不是只檢查設定檔。
2. 設計分割區撤銷與交接
cooperative rebalance 的 revoke 集合只包含必須遷移的分割區。消費者收到 revoke 後停止拉取這些分割區,完成或放棄目前批次,再同步提交已處理 offset;未被撤銷的分割區繼續消費。新持有者從已提交 offset 開始,重複訊息由業務冪等鍵或下游去重處理。
3. 處理 offset 與進行中的訊息
提交 offset 必須晚於業務副作用,避免先提交後處理造成遺失。批次處理中收到 revoke 時,設定停止旗標,讓處理器在安全點結束;逾時則停止繼續拉取並記錄未完成批次。若採用非同步處理,需維護分割區內序號,只有連續完成的前綴才能提交。
4. 規劃滾動發布步驟
發布控制器按小批次重啟成員,每批等待群組穩定與 lag 恢復。步驟包括:記錄基線、升級用戶端、觀察協定、切換首選 assignor、逐步擴縮容演練,再擴大批次。任何階段出現 rebalance 風暴或延遲超閾值,都暫停推進,不要同時修改 session timeout、max poll interval 等多個變數。
5. 設計故障與回滾
成員崩潰時,協調器在 session timeout 後重新分配其分割區;新成員從最後提交 offset 復原,可能重複處理崩潰前已產生副作用的訊息。回滾時把舊 assignor 放回相容清單,按相同滾動順序恢復,不要強行刪除仍在執行的新成員。記錄 generation、成員 ID、分割區撤銷與提交失敗,便於定位交接競態。
6. 建立容量與觀測護欄
核心指標包括 rebalance 頻率與持續時間、每次撤銷分割區數、consumer lag、poll 間隔、提交延遲、重複消費率與未分配成員數。壓測至少涵蓋成員同時重啟、熱點分割區、處理時間超過 max.poll.interval、網路抖動與分割區數接近成員數。容量不足時先降低發布批次或增加消費者,再繼續遷移。
高品質示範回答
我會先確認所有用戶端都支援 cooperative 協定,再採用兩階段滾動設定:第一階段保留相容 assignor 完成版本升級,第二階段把 CooperativeStickyAssignor 設為首選並移除舊策略。revoke 回呼只停止即將遷移的分割區,先完成安全點並提交連續 offset;未撤銷分割區繼續工作。新持有者從已提交 offset 讀取,重複消費由冪等鍵處理。發布控制器按小批次推進,觀察 rebalance、lag、poll 間隔、提交失敗與重複率。崩潰依靠 session timeout 重新分配,回滾使用相容清單與相同滾動順序,避免強制清理正在執行的成員。
常見錯誤
- 只改一台消費者設定,忽略 assignor 是群組級協商。
- 把 cooperative 當成完全沒有暫停,忽略被撤銷分割區仍需交接。
- 在業務副作用前提交 offset,造成訊息遺失。
- revoke 時繼續拉取或提交不連續的非同步結果。
- 同時調整多個逾時參數,無法判斷延遲變化來源。
- 只看 lag,不觀察 rebalance 頻率、撤銷集合與重複消費。
追問及應對
cooperative 能保證零重複嗎?
不能。崩潰、提交重試與 revoke 邊界都可能造成重複,目標是減少全組暫停並把重複窗口控制在可接受範圍。下游仍需冪等或去重。
為什麼必須全組支援 cooperative?
assignor 協定需要成員共同協商。舊成員不能解析或執行 cooperative 語意時,混用會導致協商失敗或回到 eager 行為,因此要先完成相容版本升級。
處理時間超過 max.poll.interval 怎麼辦?
拆小批次、把處理移到可控的非同步池或調整參數,並確保每次 poll 仍按時呼叫。不能只增大逾時而忽略失敗檢測變慢與分割區占用時間變長。
如何驗證回滾安全?
在預發布群組注入成員崩潰、網路抖動與提交失敗,記錄 generation、offset、撤銷集合與副作用去重結果;驗證舊 assignor 能在相容矩陣內重新穩定,且沒有跳過未提交 offset。