把資料搬進來:批次還是串流?讀《Fundamentals of Data Engineering》Ch.7

· tech

#data-engineering#book-notes#ingestion

源頭生出資料、儲存準備好接,中間那條把資料搬進來的動作,就是這章的主角:Ingestion(擷取)。它是生命週期的第二站,也是最多人一上來就糾結「要不要即時」的地方。這章最該先想清楚的一句話是 —— 批次還是串流,不是技術品味問題,是業務價值問題。

先問對問題:ingestion 的幾條關鍵軸

書提醒:在選任何工具之前,先想清楚這幾個面向。它們合起來決定你的擷取長什麼樣:

面向在問什麼
頻率批次?串流?還是介於中間的微批次?(下節主角)
有界 / 無界一份固定的檔,還是永不結束的事件流?
push / pull來源主動送,還是你主動去拿?(見下)
同步 / 非同步要等它完成,還是丟了就走?
payload資料多大、什麼格式、schema 會不會變?(源頭那章的痛)
可靠性掉一筆會怎樣?能不能重送、去重?

這些問題的答案,幾乎都指向同一個核心決定:多即時?

核心光譜:批次 ↔ 微批次 ↔ 串流

「批次還是串流」其實不是二選一,而是一條光譜。往即時走一步,就多付一分複雜度與成本:

批次 Batch 小時 ~ 天 定時/定量・成熟(預設) 微批次 Micro-batch 秒 ~ 分 每一小批處理一次 串流 Streaming 毫秒 ~ 秒 逐筆事件・即時 高延遲・低複雜・便宜 低延遲・高複雜・貴 每往即時走一步,就多付一分複雜度與成本
擷取頻率是一條光譜,不是二選一;批次仍是成熟、便宜的預設,串流用延遲換來的即時,代價是複雜度與成本

微批次(如 Spark Structured Streaming)是實務上很甜的中間點 —— 用「每幾秒跑一小批」逼近串流的即時,卻大致沿用批次那套熟悉的心智與工具。很多「我們需要即時」的需求,其實微批次就滿足了。

批次抽取的兩種姿勢:快照 vs 增量

走批次時,還有一個常踩的坑 —— 每次要搬整份還是只搬新的?

  • 快照(snapshot):每次抓整張表的當下狀態。簡單、好推理,但資料一大就重、又慢又貴。
  • 增量(differential / incremental):只抓上次之後變動的部分。省很多,但你得有辦法知道「哪些變了」—— 時間戳記、遞增 id,或更漂亮的 CDC(讀資料庫變更日誌)

小資料用快照省心,資料一大就得改增量。 這是批次擷取從能跑到跑得起的分水嶺。

Push、Pull 還是 Poll:誰發起這件事

另一個容易混的維度:資料的移動,是誰主動?書分成三種模式:

Push 來源發起 來源 Ingestion 事件一發生就送(webhook・producer) Pull 你發起 來源 Ingestion ① 我發請求 ② 資料回來(DB query・API GET) Poll 你定期問 來源 Ingestion 定期問:有新的嗎?(×N,有才回傳)
Push 是來源主動送(webhook、串流 producer);Pull 是你主動去要(查 DB、打 API);Poll 是你定期去問有沒有新的 —— 決定了誰扛延遲與負載

這三種不只是名詞:push 通常對應串流與低延遲,pull / poll 對應批次。poll 太密會壓垮來源、太疏又延遲高,所以能 push(或 CDC)時,往往比狂 poll 漂亮。

該不該上串流?書的答案很克制

講到這你可能想:那就上串流嘛,即時多好。但書(和我)的立場很保守:批次到今天仍是預設,串流是為了業務價值才上的例外。 兩個先問自己的問題:

  1. 即時真的有價值嗎? 報表明天看和五秒後看沒差,那串流只是徒增成本。
  2. 下游用得到即時嗎? 你辛苦串流進來,結果下游還是每天跑一次批次分析 —— 那即時在半路就被浪費掉了。

除非這兩題都是「是」,否則別為了即時而即時。這跟我那篇 先確認痛點,再上重武器完全同調 —— 串流是重武器,先確認你真的痛。

怎麼把資料搬進來:別自己造輪子

最後是實際的搬運方式。書列了一整排,我按「你要碰多少底層」排:

方式場景
直連資料庫(JDBC/ODBC)最原始,自己查自己搬
CDC讀變更日誌,近即時又不壓主庫
API第三方 SaaS 的標準入口
訊息 / 事件串流即時事件,見 Kafka
託管連接器(Fivetran、Airbyte)常見來源直接接好,免自己維護

最後一列是重點:擷取這種「大家都在做、又沒差異化」的粗活,優先用託管連接器,別自己刻一堆 API 串接又自己養。這正是 Ch.4「預設買 / 用現成」在擷取這一站的落地。

反思

「要不要即時」是我看過最常被問錯的問題

幾乎每個資料需求,一開口都是「我要即時」。但這章把問題導正了:先問即時有沒有價值、下游吃不吃得下,再決定頻率。 我遇過太多「說要即時」的需求,追下去發現使用者其實一天看一次報表 —— 那串流純粹是給自己找維運。我現在的預設反過來:先問能不能批次解決,不行、且即時真的有商業價值,才往微批次、再往串流爬。批次不是落後,是還沒被證明不夠用之前最理性的選擇。

微批次是我最常推的「剛剛好」

真的需要更快時,我很少一步跳到逐筆串流,而是先試微批次Structured Streaming那種「每幾秒一小批」,大致沿用批次的心智與除錯方式,卻把延遲壓到秒級 —— 對絕大多數「想要更即時一點」的需求綽綽有餘,又躲掉了純串流那套狀態、亂序、exactly-once 的複雜度。用最小的複雜度增量換到夠用的即時,是我做擷取時反覆用的一條原則。

push / CDC 讓我少 poll 出很多禍

早年我做擷取很愛用 poll —— 每分鐘去問來源一次,簡單直覺。但量一上來就兩難:問太密壓垮來源、問太疏又延遲高。後來學會能 push 就 push、能讀日誌就 CDC,很多這種兩難直接消失:資料一有變動就流過來,我不用一直敲門。這跟 上一章「借力資料庫本來就在寫的 log」是同一種聰明 —— 與其自己狂輪詢,不如讓來源在對的時機告訴你。