資料處理是一個不斷演進的領域,面對更大的資料集、更密集的資料轉換,以及對快速、可靠且低成本結果的需求。資料處理管線(data processing pipeline)能將來自各種來源(行動裝置使用統計、感測器網路、網站應用日誌等)的無界、無序、全球規模的資料集,轉換為結構化、索引化的儲存,支撐關鍵業務決策或產品功能。本章涵蓋管線應用類型、需求識別與設計模式、開發生命週期最佳實踐,以及 Spotify 的事件交付系統案例研究。

管線應用類型#

管線可以包含多個階段(stage),每個階段是一個獨立的處理程序,彼此存在依賴關係。以下是幾種常見的管線應用:

ETL(Extract Transform Load)資料轉換#

ETL 模型是資料處理中的常見範式:從來源擷取資料、進行轉換(可能包含反正規化),然後重新載入到特定格式。轉換階段可以:

  • 變更資料格式以新增或移除欄位
  • 跨資料來源進行聚合計算
  • 為資料建立索引,改善下游服務消費資料的特性

典型的 ETL 管線範例包括:機器學習或商業智慧的前處理、事件計數、帳單報告計算、以及驅動 Google 網頁搜尋的索引管線。

資料分析(Data Analytics)#

商業智慧(Business Intelligence)是指用於收集、整合、分析和呈現大量資訊的技術與實踐。本章以虛構的 Shave the Yak 手機遊戲為例:業務主管需要每月報告最常使用的功能,以規劃新功能開發。團隊將行動和網頁分析資料儲存在 BigQuery 中,每天由 Google Analytics 更新三次,並在新資料到達時觸發彙整作業。

機器學習(Machine Learning)#

ML 系統通常包含五個階段:

  1. 從大型資料集中擷取特徵(features)和標籤(labels)
  2. 使用 ML 演算法訓練模型
  3. 在測試資料集上評估模型
  4. 將模型提供給其他服務使用(serving)
  5. 其他系統根據模型回應做出決策

Figure 13.1: ML data processing pipeline

本章以虛構的線上洋裝公司 Dressy 為例,展示如何建構推薦系統管線。Dressy 選擇使用 clustering filter,透過 streaming Dataflow pipeline 前處理資料,再用 TensorFlow 訓練模型來提供個人化推薦。

當推薦結果不正確或過時時,應檢查:資料是否卡在管線中無法被前處理?ML 模型是否有軟體錯誤?生產環境是否在使用過時的模型版本?

管線最佳實踐#

定義與衡量 SLO#

自動偵測管線健康狀況並在超出 error budget 前收到通知,能最大限度減少對客戶的影響。

資料新鮮度(Data Freshness)SLO 格式:

  • X% 的資料在 Y 秒/分/天內處理完成
  • 最舊的資料不超過 Y 秒/分/天
  • 管線作業在 Y 秒/分/天內成功完成

資料正確性(Data Correctness):

  • 使用測試帳戶產生「golden data」,比較預期與實際輸出
  • 設定例如每季度不超過 0.1% 的發票錯誤率
  • 監控錯誤/差異並實施閾值告警

資料隔離/負載平衡(Data Isolation/Load Balancing):

  • 高優先級資料應在資源受限時優先處理
  • 可透過不同佇列、不同作業設定或不同資源配置的 worker 來實現

端到端衡量(End-to-End Measurement):

  • 避免僅衡量每個階段的 SLO,因為客戶只關心所有階段總和的 SLO
  • 僅衡量每階段的資料正確性可能會遺漏端到端的資料損壞錯誤

如果每個階段各自報告一切正常,但某階段引入了一個它期望下游處理的欄位,而下游卻丟棄了該資料,最終使用者就看不到資料。僅按階段監控無法捕捉這類問題。

規劃依賴故障#

  • 確認是否過度依賴其他產品的 SLO/SLA
  • 至少為其廣告的最大故障情境進行設計
  • Google 透過 Disaster Recovery Testing (DiRT) 演練計畫性中斷,測試管線的自動故障轉移能力

建立與維護管線文件#

Figure 13.2: Pipeline system diagram (PII = personally identifiable information)

應維護三類文件:

  • 系統圖(System Diagrams): 顯示每個元件(管線應用和資料儲存)及每步轉換,包含監控和除錯資訊的快速連結
  • 流程文件(Process Documentation): 記錄常見任務(發布新版本、變更資料格式)和較少見的手動任務(初始服務啟動、區域關閉)
  • Playbook 條目: 每個告警條件都應有對應的恢復步驟

對應開發生命週期#

Figure 13.3: Pipeline development lifecycle with release workflow

管線的開發生命週期包含以下階段:

  1. 原型開發(Prototyping): 驗證語義和業務邏輯表達能力,比較程式模型(如 Dataflow vs. MapReduce、batch vs. streaming)
  2. 1% Dry Run 測試: 使用生產資料在非生產環境中運行,逐步擴大規模並追蹤效能
  3. 預發布環境(Staging): 使用盡可能接近實際生產資料的環境,執行 A/B 比對
  4. 金絲雀部署(Canarying): 部分部署管線並監控結果,可使用 two-phase mutation 技術處理生產資料但跳過寫入生產儲存
  5. 部分部署(Partial Deployment): 對重大功能變更先在少量資料上測試(如 1%、10%、50%、100%)
  6. 部署到生產環境: 確認問題已排除後完全推廣,並確保能快速從已知良好狀態恢復

減少熱點(Hotspotting)#

熱點是資源因過度存取而超載導致操作失敗。常見範例包括:

  • 多個 pipeline worker 同時存取單一 serving task 造成過載
  • 單一機器上的資料因大量並行存取導致 CPU 耗盡
  • 資料庫行級鎖競爭造成延遲
  • 需要大量資源的大型工作單元

應對策略包括:重構資料或存取模式以均勻分散負載、降低負載、減少鎖粒度、建立緊急停止機制以隔離問題資料。

實施自動擴展與資源規劃#

  • 使用自動擴展處理工作負載高峰,避免全時為峰值負載佈建資源
  • 預測未來成長並分配容量,同時注意不僅是管線作業本身的成本,還包括跨區域資料複製和網路頻寬成本
  • 雖然管線效能應以端到端 SLO 衡量,但資源使用應在每個階段個別衡量

遵循存取控制與安全策略#

  • 避免在暫存儲存中存放 PII(個人識別資訊),若必要須加密
  • 限制每個管線階段僅擁有讀取前一階段輸出所需的最小存取權限
  • 對日誌和 PII 設定 TTL(Time to Live)限制

規劃升級路徑#

設計管線時應確保系統故障不會觸發 SLO 違規。當收到告警時,所有自動化措施應已用盡。擁有明確的 SLO、可靠的指標和告警偵測,能在客戶察覺前發出通知。

管線需求與設計#

推薦的管線功能特性#

管理資料處理管線時應最佳化的功能包括:

  • 延遲(Latency): 支援串流、批次或兩者兼備的 API
  • 資料正確性: Exactly-once 語義、two-phase mutations、windowing 函式
  • 高可用性: 多區域部署(multihoming)、自動擴展
  • MTTR(平均修復時間): 綁定程式碼變更到 release 以快速回滾、測試過的資料備份與還原程序
  • MTTD(平均偵測時間): SLO 監控,基於症狀而非原因的告警
  • 開發生命週期: 在金絲雀環境測試後再部署到生產
  • 資源檢查與預測: 建立資源會計儀表板,建立成長關聯或預測指標

冪等與兩階段變更(Idempotent and Two-Phase Mutations)#

冪等變更(Idempotent Mutation): 可多次套用產生相同結果的變更類型,確保管線以相同輸入重新執行時總是產生相同結果。

Figure 13.4: Two-phase mutation

兩階段變更(Two-Phase Mutation): 資料被讀取和轉換後,變更本身先儲存在暫存位置。一個獨立的驗證步驟針對這些潛在變更進行正確性驗證,通過後才套用到生產環境。這在金絲雀測試時特別有用。

檢查點(Checkpointing)#

管線是長時間運行的程序,若中途終止將失去狀態。檢查點技術讓管線能定期將部分狀態儲存,以便稍後恢復。這對建立 AI 模型的管線尤其重要,因為每次模型計算迭代都依賴先前的計算結果。

程式碼模式#

  • 程式碼重用: 實作可重用的程式庫,讓監控指標能在一處新增並跨多個管線共享
  • 微服務方式: 建立較小的管線而非單一巨型管線,使其可獨立發布和監控

管線成熟度矩陣(Pipeline Maturity Matrix)#

Google 使用管線成熟度矩陣作為管線技術選擇或設計的諮詢工具,衡量五個關鍵特性(每項從 1 到 5 分):

特性1 - Chaotic3 - Functional5 - Continuous Improvement
故障容忍無故障轉移支援支援 work unit 重試多區域自動故障轉移、自動重試與隔離
可擴展性無自動擴展,手動介入使用額外工具自動擴展內建自動擴展、動態重新分片、負載卸除
監控與除錯無日誌,無法追蹤失敗可識別失敗單元並擷取日誌自動隔離與重播失敗單元、完整執行地圖視覺化
易用性與透明度無可發現性,設定成本高部分可重用元件全域資料註冊服務、最小程式碼配置、完整文件
單元與整合測試無測試框架需長時間、資源密集支援 sanitizer、程式碼覆蓋率、內建測試資料生成

管線故障:預防與回應#

常見故障模式#

延遲資料(Delayed Data):

  • 管線輸入或輸出延遲時,下游作業可能在沒有必要資料的情況下開始運行
  • 過時的資料幾乎總是比不正確的資料好
  • 建立被所有階段遵守的資料依賴關係至關重要

損壞資料(Corrupt Data):

  • 未偵測到的損壞資料可能導致使用者可見的問題
  • 修復兩個主要步驟:防止更多損壞資料進入系統、從先前已知良好版本還原或重新處理
  • 考慮選擇性重新處理,僅處理受影響的使用者或帳戶

潛在原因#

  • 管線依賴: 儲存、網路系統或其他服務可能在限流或拒絕新資料
  • 管線應用或設定: 瓶頸、程式錯誤、設定錯誤(如 CPU 密集處理、效能退化、記憶體不足)
  • 意外的資源成長: 突然且非預期的系統負載跳升
  • 區域級中斷: 單區域管線特別脆弱,多區域管線需注意資料可能被擱置或延遲

案例研究:Spotify 事件交付系統#

Spotify 每天從其應用程式中擷取並發布數千億個事件(使用者聽歌、點擊廣告、追蹤播放清單等),用途包括 A/B 測試分析、顯示播放次數、驅動個人化探索播放清單,以及向藝術家支付版稅。

事件交付#

所有已交付的事件按類型和發布時間分區。在任何給定小時內發布的事件被分組儲存在一個稱為 delivered hourly bucket 的指定目錄中,再按事件類型分組。

Figure 13.5: Delivered hourly buckets

事件交付系統架構#

系統設計的關鍵決策是將資料收集與資料交付解耦。使用 Google Cloud Pub/Sub 作為中間層,使兩者成為獨立的故障域,限制生產問題的影響範圍。

Figure 13.6: Event delivery system architecture

資料收集:

  • 事件按事件類型分組,每種事件類型有完全的隔離
  • 各事件類型發布到 Google Cloud Pub/Sub 中的專屬 topic
  • 發布由運行在 Spotify 資料中心和 Google Compute Engine 上的微服務執行

ETL 流程:

  1. 專用微服務從事件串流中消費事件
  2. 另一個微服務將事件分配到其小時分區
  3. 運行在 Dataproc 上的批次作業對事件去重複並持久化到 GCS 上的最終位置

資料交付:

  • 客戶(Spotify 內部工程團隊)透過簡單設定動態啟用或停用事件類型交付
  • 使用 GCE Autoscaler 達成最佳資源利用

SLO 定義#

Spotify 為事件交付系統提供三種 SLO:

即時性(Timeliness):

Figure 13.7: Event time partitioning

  • 定義為交付一個小時資料桶的最大延遲
  • 使用內部工具 Datamon 衡量和視覺化

Figure 13.8: Datamon for Spotify's data monitoring system

  • SLO 分為三個優先級層:高、正常、低
  • 下游資料作業在依賴的小時桶交付前無法開始處理

偏斜度(Skewness):

Figure 13.9: Delivery of skewed data

  • 定義為每日可被錯置的最大資料百分比
  • 由於系統使用啟發式方法判斷何時交付小時桶,已交付桶中未交付的事件可能被錯誤地交付到未來的小時桶
  • 偏斜會導致某些時段先低報再高報數值

完整性(Completeness):

  • 定義為事件成功發布到系統後被交付的百分比
  • 每日報告偏斜度和完整性,使用內部審計系統比較所有已發布和已交付事件的計數

Spotify 使用伺服器端收到事件的時間戳而非客戶端產生的時間戳,因為使用者可能在離線模式下緩衝事件長達 30 天,且使用者可修改裝置系統時間。

客戶整合與支援#

  • 完全託管服務: 隱藏系統複雜性,讓客戶專注於自身問題
  • 有限功能: 僅支援特定的內部格式發布事件,僅交付到小時桶且使用單一序列化格式
  • 顯式啟用: 客戶啟用事件交付時需定義是否為財務相關事件、即時性要求和事件擁有權
  • 文件即產品: 所有支援請求被視為文件問題或產品問題

系統監控#

  • SLO 監控提供系統整體健康的高階洞察,但 SLO 違規告警意味著客戶已受影響
  • 需要足夠的操作監控以在 SLO 被破壞前解決或減輕問題
  • 補充應用日誌,但注意避免過度記錄——對高流量元件記錄每個請求並無價值

容量規劃#

  • 大多數元件基於 CPU 使用率進行容量規劃,佈建為尖峰時段 50% CPU 使用率
  • 使用 GCE Autoscaler 改善資源利用
  • Autoscaler 的陷阱:若 CPU 使用率與實際工作量失去關聯,Autoscaler 會無限擴展直到耗盡所有資源
  • 防護措施:限制 Autoscaler 最大實例數、嚴格限制 daemon 的 CPU 使用、偵測到無用工作時積極節流

開發流程#

Figure 13.10: Development process

Spotify 採用 CI/CD 流程:

  • 遵循「測試金字塔」哲學:大量單元測試、較少整合測試、系統級端到端測試
  • 每次變更都經過同儕審查,所有測試在共用 CI/CD 伺服器上執行
  • 部署採分階段策略,需手動審批才能進入下一階段:
    1. 部署到預發布環境(映射生產流量的代表性片段)
    2. 部署到少量生產實例(金絲雀)
    3. 完整生產部署

事件處理#

  • 首要目標是減輕損害並恢復到穩定的先前狀態
  • 事件期間避免部署重大變更,除非事件由近期部署的新程式碼引起
  • 最常見的操作故障來源:系統故障(軟體錯誤或效能退化)和外部服務故障
  • 資料新鮮度 SLO 被破壞:客戶只需等待資料到達
  • 偏斜度或完整性 SLO 被違反:可能需要通知客戶,因為資料品質受損,需重新交付或重新整理事件

Spotify 的事件交付系統經過多年演進。先前版本遠不如現在可靠,工程師每幾個晚上就被叫醒。設計現行版本時,他們專注於建構模組化系統,做好一件核心事:交付事件。

結論#

將 SRE 最佳實踐應用於管線,有助於做出明智的設計選擇並開發自動化工具,使管線更易操作、更有效擴展且更可靠。關鍵要點包括:

  • 了解需求並選擇 SLO,以此驅動設計決策
  • 評估可用技術,根據管線成熟度矩陣衡量關鍵特性
  • 建立完整的開發生命週期,從原型到金絲雀再到生產部署
  • 為故障做好準備,包括資料延遲、資料損壞和區域級中斷
  • 記錄設計並建立執行常見任務的文件,減少中斷時間

無論是直接擁有管線,還是擁有依賴管線產出資料的服務,都應確保 SRE 從早期階段就參與管線設計工作,以確保管線可以輕鬆發布、修改和運行而不會造成客戶問題。