題幹與適用場景
把它當作資料工程設計題。假設尖峰每秒 2,000 個訂單事件、新鮮度目標 15 分鐘、必填欄位完整率目標 99.5%。契約需要涵蓋結構、含義、品質、服務等級、責任人、隱私標籤,以及如何修改承諾。
邊界是上游生產者與下游消費者之間的資料產品。資料庫表定義太窄,無法說明 total_amount 是否含稅、誰負責資料流,或錯過新鮮度目標後如何處理。
面試官考察點
面試官要聽到一個可執行、有版本、有責任人的契約。只列出 Avro 或 JSON Schema 屬於弱回答;強回答會區分相容性與語意正確性,把檢查放在生產邊界,並給消費者明確的違約與遷移路徑。
你需要把每個欄位連到消費者決策:拒絕、隔離、轉換、告警,或帶著明確的降級狀態繼續。還要解釋怎樣避免契約變成無人維護的審批佇列。
回答前需要澄清的問題
- 來源是只追加事件流、可變資料表,還是兩者都有?可變快照還需要鍵、更新語意和刪除規則。
- 哪些保證是發布閘門?付款事件的貨幣無效應拒絕,非必要行銷標籤則可隔離。
- 消費者能否落後一版?可以的話要提供相容視窗和轉換;不可以則需要協調切換。
- 事件能否重播,是否含個人資料?重播能力影響保留期,隱私標籤影響去識別、存取和刪除。
30 秒回答框架
「我會先從消費者用例出發,寫一份有版本的機器可讀契約。它定義 Schema 與語意、必填欄位和域檢查、新鮮度與完整率 SLO、責任人、隱私標籤和演進策略。生產者發布前檢查,註冊中心在 CI 檢查相容性;執行時把壞記錄隔離並暴露指標。新版本預設採增量演進,語意破壞時用雙寫或轉換視窗。每次違約都有負責人、重播路徑和消費者可見狀態。」
分步驟深入解答
1. 定義契約物件
為資料集設定識別碼與版本。每個欄位記錄型別、可空性、單位、業務含義、允許值、敏感程度,以及是否允許未知欄位。訂單事件要說明 occurred_at 是事件時間、金額是否為最小貨幣單位,以及取消訂單是否仍可見。
加入責任人、支援管道、保留期、新鮮度、交付頻率和可用性。服務等級必須可測量:新鮮度可以是最新合格記錄的年齡,完整率可以是視窗內必填欄位非空比例。
2. 按失敗模式拆分檢查
Schema 檢查發現缺欄位和不相容型別;域檢查發現負金額或不支援的貨幣;關係檢查發現重複事件 ID 或跳過狀態的訂單;新鮮度和量級檢查發現生產者停發或分割區不完整。
將結果連同契約版本、生產者建置版本、分割區、樣本視窗和失敗規則保存。這樣消費者才能決定暫停、回填,或接受有邊界的降級。
3. 在發布前後執行
CI 中把候選 Schema 與註冊版本比較,並用樣本資料執行契約測試。執行時在事件進入共享流前於生產者邊界檢查。壞記錄進入隔離流,保留原始載荷、失敗規則、契約版本和重播鍵。
消費者仍應檢查關鍵不變量。生產端檢查能預防許多事故,但消費者檢查可以保護路由錯誤、舊生產者和轉換缺陷。
4. 把演進寫成規則
只有舊消費者能容忍未知欄位時,新增可選欄位才可能保持相容。重新命名會破壞契約,因為欄位名稱或含義改變。優先採用新增並棄用:發布新欄位,雙寫或轉換,遷移消費者,統計舊欄位讀取量,再按約定視窗下線。
例如把 total_amount 從含稅改成未稅,使用新版本或新欄位比複用原名安全。若消費者必須繼續使用舊視圖,就提供版本化轉換,並標記轉換值。
5. 定義違約處理
使用嚴重等級。付款事件格式錯誤就拒絕並隔離;新鮮度違約通知負責人並標記資料過期;非關鍵描述失敗則可繼續但必須記錄指標。契約要寫明誰能臨時放行、放行多久、需要什麼證據。
不要靜默丟棄。按生產者和契約版本記錄接收、拒絕、隔離、重播和重複數量。重播必須具備冪等性,接收端用事件 ID 與契約版本避免產生第二次業務效果。
6. 驗證運作模型
用固定樣本做契約測試,每個新版本做相容性測試,再在生產分割區抽樣做金絲雀檢查。涵蓋延遲事件、重複 ID、未知列舉、必填欄位為空、時區錯誤和生產者停止傳送。
儀表板要同時顯示違約率、新鮮度年齡、完整率、消費者延遲、隔離深度、重播成功率和負責人確認時間。Schema 檢查通過但資料過期,仍然代表資料產品失敗。
高品質示範回答
「我會把訂單流當成有版本的資料產品。先列出消費者並定義事件語意:事件時間、金額單位、貨幣、身分和狀態轉移。契約隨後包含 Schema、域規則、關係規則、新鮮度與完整率 SLO、責任人、保留期和隱私標籤。
「註冊中心在 CI 拒絕不相容變更。生產者發布前檢查,執行時把壞記錄連同失敗規則和契約版本送進隔離流。消費者仍保留少量關鍵檢查,因為路由或轉換仍可能出錯。
「我會預設採用增量演進。重新命名或語意變化時新增欄位或版本,雙寫、遷移消費者、統計舊欄位讀取量,再在相容視窗結束後下線舊版本。新鮮度和品質違約都要有嚴重等級、負責人、告警和重播流程。最後用固定樣本、金絲雀、延遲與重複事件,以及新鮮度、完整率、隔離深度和重播正確性指標驗證。」
常見錯誤
- 錯誤表現 → 失敗原因 → 修正方法: 把 Schema 當成完整契約 → 語意和責任人仍是隱含約定 → 補充含義、SLO、責任人和變更策略。
- 錯誤表現 → 失敗原因 → 修正方法: 同步拒絕所有壞記錄 → 一個壞事件可能阻塞整個分割區 → 用背壓受控的隔離流和重播鍵處理。
- 錯誤表現 → 失敗原因 → 修正方法: 認為新增欄位總是安全 → 嚴格消費者可能無法處理未知欄位 → 先驗證消費者相容性。
- 錯誤表現 → 失敗原因 → 修正方法: 只告警 Schema 不匹配 → 過期或不完整資料仍可能通過 → 監控新鮮度、量級、完整率和業務不變量。
- 錯誤表現 → 失敗原因 → 修正方法: 改變含義後複用欄位名 → 歷史值和新值無法比較 → 新建版本或明確轉換欄位。
追問及應對
如果生產者不能同時升級怎麼辦?
保留舊契約,新增欄位或版本,在可衡量的視窗內同時接受兩者。相容適配器可以轉換舊輸入,但必須暴露資訊損失和下線日期,不能隱藏差異。
契約測試通過但指標仍然錯誤怎麼辦?
這屬於語意漂移。增加業務不變量或對帳檢查,與獨立來源比較,並把爭議定義寫回契約。結構相容不能證明生產者套用了正確業務規則。
如何避免隔離區變成資料墳場?
為每條規則指定負責人和處理目標,保留原始載荷與契約版本,統計佇列年齡和重播成功率。每日複盤將失敗歸類為生產者缺陷、契約缺陷或預期例外。
什麼時候不值得使用完整資料契約?
只有一個負責人、短期存在且沒有下游承諾的私有表,可以只使用輕量 Schema 和測試。當多團隊共享、需要重播、含受監管欄位或有新鮮度承諾時,再引入完整契約。