題干與適用場景
這是資料平台、即時分析與資深資料工程職位常見的系統設計題。輸入峰值為每秒 50,000 個事件,營運看板要求 60 秒內可見,財務報表要求前一天資料在 7:00 前完成。題目要判斷共享執行圖何時會把嚴格 SLO 傳遞給所有消費者,以及如何用獨立消費進度與資源池降低耦合。
面試官考察點
- 能否先把「即時」和「按時完成」寫成端到端 SLO,而不是直接報工具名稱。
- 能否區分 Beam 圖內分支、同一訊息來源的獨立訂閱與完全獨立的計算資源。
- 能否解釋重複讀取、成本、背壓、重播、延遲事件與故障域之間的取捨。
- 能否給出指標、灰度、回滾和資料對帳,證明拆分真的改善使用者結果。
回答前需要釐清的問題
先確認 60 秒是事件時間到看板的端到端新鮮度,還是處理器延遲;財務報表是否允許延遲分區在次日補算;兩個消費者能否共享原始儲存;事件是否需要依租戶或優先級公平處理;重複、遺失與順序的容忍度;以及預算更看重成本還是看板尾延遲。若報表只是 T+1,而看板是嚴格低延遲,兩個 SLO 已經暗示資源隔離值得優先評估。
30 秒回答框架
我會先寫清兩個消費者的端到端 SLO、資料正確性與恢復目標。若一條共享管線必須同時滿足最嚴格的 60 秒目標,我會先建立單管線基線,再用獨立訂閱把即時和批次的消費進度隔開;計算代價高的公共解析可以共用,資源緊張或故障傳播明顯時再拆成獨立作業。每條路徑都記錄延遲、積壓、遲到、重複與報表完成時間,並用重播和故障注入驗證拆分是否值得。
分步驟深入解答
1. 從 SLO 推導結構
把即時路徑定義為「事件時間到可查詢時間的 p99 不超過 60 秒」,把批次定義為「前一天有效事件在 7:00 前完成,遲到資料進入受控補算窗口」。Google Dataflow 文件強調,混合 SLO 的單一管線必須承受更嚴格的目標;這會讓低優先級工作共享即時資源。若兩個 SLO 的預算、告警與擴容策略不同,獨立路徑更容易解釋與維運。
2. 比較三種拓撲
單一管線分支適合公共解碼與輕量路由,單次處理事件後輸出多個集合,避免重複執行昂貴解析。Beam 文件說明,同一 PCollection 可被多個轉換讀取,但每個轉換都會再次處理輸入;單一多輸出轉換可讓每個元素只經過一次公共計算。
同一主題的獨立訂閱適合讓即時與批次擁有各自的確認、積壓與重播進度。Google Dataflow 文件給出的多管線方案正是利用獨立訂閱,讓不同作業獨立拉取並確認訊息。完全獨立的作業再進一步隔離 CPU、記憶體、發布節奏與故障域,代價是重複讀取、重複序列化與更高維運成本。
3. 設計推薦路徑
我會保留一個不可變原始事件層,並從同一來源建立即時訂閱與批次訂閱。即時作業只做輕量聚合並寫入低延遲查詢層;批次作業依事件日期讀取保留資料,寫入分區表。公共解析若占總 CPU 的 20% 以上,可在入口做一次規格化並把版本化事件寫入原始層;不要把即時作業的處理進度當成批次提交證據。
raw-events
-> realtime-subscription -> stream-aggregate -> serving-store
-> batch-subscription or retained-raw -> daily-transform -> partitioned-lake4. 處理背壓、優先級與成本
即時路徑設定獨立並發上限與積壓告警;批次在即時資源緊張時降低並發,但不能共享同一個無界佇列。若成本不允許兩套完整計算,先共享解碼與落盤,再隔離下游計算。若即時積壓超過 60 秒,暫停擴大批次並優先恢復即時 SLO。每條路徑依輸入位元組、處理 CPU、積壓年齡與單位輸出成本計費,不能只比較作業數量。
5. 遲到、重播與故障恢復
即時窗口使用 watermark 與有限 allowed lateness;超窗事件進入遲到佇列或原始層,由批次補算並以版本號覆蓋受影響分區。每條路徑都用事件 ID 或業務主鍵實作冪等寫入。重播時從保存的來源位置建立新訂閱,禁止把生產消費者的確認位倒退到舊位置。若即時作業失敗,批次仍應能從原始層恢復;若原始層不可用,兩條路徑都要明確降級與告警。
6. 用驗收實驗決定是否拆分
先執行共享基線,再對少量租戶啟用獨立資源。比較看板 p50/p95/p99 新鮮度、批次報表完成時間、消費積壓、重複率、重播耗時、CPU、儲存與每百萬事件成本。注入批次突發、即時處理器重啟、訊息重複、分區遲到與訂閱暫停,驗證即時 SLO 是否仍滿足。若拆分只降低作業延遲卻增加重複資料或成本超過預算,應保留共享方案並繼續優化公共步驟。
高品質示範回答
我會先把兩個目標寫成端到端 SLO:看板從事件時間到可查詢時間 p99 不超過 60 秒,財務報表在次日 7:00 前完成,遲到資料進入有限補算窗口。先做一條共享管線基線,但不會讓批次與即時路徑共用確認位。我的預設設計是同一個不可變原始事件層、兩個獨立訂閱與兩個下游作業;即時作業做輕量聚合,批次作業依事件日期讀取保留資料。公共解析可在入口版本化一次,只有在資源或故障域需要時才拆出完整作業。兩條路徑分別監控新鮮度、積壓、遲到、重複、報表完成時間與單位成本,重播使用新訂閱與冪等鍵。透過批次突發、重啟與遲到事件的故障注入驗證;如果拆分沒有改善使用者 SLO,就回退到共享計算並優化公共階段。
常見錯誤
- 錯誤表現: 因為有兩個消費者就複製兩套完整管線。失敗原因: 公共解析與落盤成本被無謂加倍。修正方法: 先共享不可變原始層,再依 SLO 隔離下游計算。
- 錯誤表現: 用一個全域消費位驅動即時與批次。失敗原因: 慢消費者會拖住快消費者,重播也無法獨立。修正方法: 使用獨立訂閱或可證明獨立的消費進度。
- 錯誤表現: 只看處理器延遲,不看事件到使用者可見的延遲。失敗原因: 儲存、查詢與下游刷新仍可能超時。修正方法: 記錄端到端新鮮度與分位數。
- 錯誤表現: 遲到事件直接寫回即時結果。失敗原因: 可能重複計數或破壞已發布報表。修正方法: 設定 watermark、補算窗口、版本與冪等鍵。
- 錯誤表現: 用重啟生產消費者的方式回放歷史。失敗原因: 會擾亂線上確認位並放大流量。修正方法: 從保留來源建立獨立回放訂閱並限速。
追問及應對
如果即時路徑與批次路徑都需要同一份昂貴特徵計算怎麼辦?
把特徵計算拆成版本化、可重播的中間層,先落盤再由兩條路徑讀取;只有特徵狀態必須線上且不可共享時,才接受重複計算。用 CPU、延遲與一致性實驗比較共享中間層與複製計算。
獨立訂閱會不會讓輸入成本加倍?
會增加讀取與確認開銷,但可透過共享原始落盤、壓縮、保留窗口與按需重播控制。把每百萬事件成本與即時 SLO、故障隔離收益一起評估,不能只看儲存帳單。
批次落後時,能否暫時借用即時資源?
可以設定有界、可搶占的低優先級容量,但即時路徑擁有硬上限。借用必須有租約、自動回收與獨立積壓指標,避免批次把即時 p99 推過 60 秒。
如何證明兩條路徑最終結果一致?
用相同事件版本、業務主鍵與時間邊界生成對帳集合,比較計數、金額、缺失、重複與遲到修訂。允許即時近似時,必須定義最終一致窗口與可解釋差異,不能用一次總數相等代替長期對帳。