Flink 流批一體在位元組跳動的探索與實踐

語言: CN / TW / HK

背景

位元組跳動旗下擁有今日頭條、抖音等多款產品,每天服務著數億使用者,由此產生的資料量和計算量也是很大的:

  • EB 級別海量的儲存空間

  • 每天平均 70PB 資料的增量

  • 每秒鐘百萬次數的實時推薦請求

  • 超過 400 萬核的流式計算資源、500 萬核的批式計算資源

這對我們的整個架構,包括計算架構和儲存架構都帶來了巨大的挑戰。

業務困境

如上圖所示,左邊是一個非常典型,業界應用也很多的資料鏈路圖。這個資料鏈路是一個典型的 Lamda 架構,整個資料鏈路分為批式計算鏈路和流式計算鏈路。

在位元組跳動內部,通常需要批式計算和流式計算兩條鏈路共同服務於下游的應用。

  • 批式計算鏈路中,我們主要應用 Spark 引擎,通過 Spark 引擎在批式儲存中拿到資料,經過 ETL 的計算後,存入下游的儲存,從而服務下游的應用。

  • 流式計算鏈路,也是我們整個實時推薦、實時資訊流的核心鏈路。我們會通過訊息中心件把實時資料進行快取存入,然後運用 Flink 實時計算引擎進行處理,處理後經過訊息中介軟體的快取傳輸存入下游的儲存,來服務下層的應用。

整個計算架構分成兩條鏈路,帶來了兩個比較嚴重的問題:

  1. 計算不同源

    1. 維護成本高。批式計算主要使用 Spark 引擎,流式計算使用 Flink 引擎。維護兩套引擎就意味著使用兩套程式碼,工程師的維護成本和學習成本都非常高。

    2. 資料一致性和質量難以保障。兩套程式碼之間不能相互複用,所以資料的一致性和資料的質量難以保障。

    3. 無法混合排程造成資源浪費。批式計算和流式計算的高峰期是不同的。對流式計算來說,使用者的使用高峰期一般是白天或凌晨12點之前,那麼這些時間段也就是流式計算的高峰,此時對計算資源的需求是非常高的。相對而言,批式計算對運算時間並沒有嚴格的限制,比如可以在凌晨12點之後到早上6、7點之間進行大量運算。所以,如果流式計算和批式計算的資源無法進行混合排程,那麼就無法對運算資源進行錯峰使用,造成資源的巨大浪費。

  2. 儲存不同源

    • 資料不一致,維護成本高。如果兩條鏈路同時服務於下游應用的話,那麼兩套儲存系統也是分隔開的,依然存在資料不一致的問題。同時,維護流式、批式兩套儲存系統的成本也非常高。

針對上述困境,在位元組跳動內部,我們選擇了流批一體的解決方案

什麼是流批一體

那麼,什麼是流批一體呢?

  • 從計算層面來講,就是用同一個引擎、同一套程式碼及同樣的 API ,同時處理有限的資料流和無限的資料流,同時應對線上處理和離線處理(其中有限資料的處理對應離線處理,而無限資料的處理則對應線上處理),達到降本增效的目的。

  • 在儲存方面,流批一體即儲存系統能夠同時滿足流式資料和批式資料的儲存,並能夠有效地進行協同以及元資料資訊的更新。

架構體系使用流批一體後,資料流向如下圖左邊流程圖所示。

無論是流式資料還是批式資料,都可以直接或經過簡單加工後存入統一儲存中。而後,使用流批一體統一的計算引擎進行 ETL 計算,再服務下游的應用。由此,整個流批一體的架構實質上實現了計算同源和儲存同源。

  • 計算同源。用一套程式碼、一套邏輯去處理流式任務和批式任務,達到了降本增效的目的,同時也大幅提升了資源利用率。

  • 儲存同源。在儲存方面統一儲存,避免了儲存資源的浪費,同時也在很大的程度上避免了資料不一致。

位元組跳動的流批一體實踐

在位元組跳動,我們使用 Flink 作為流批一體統一的計算引擎,Iceberg 作為流批一體統一的儲存方式。簡單的資料流向如下圖。

在上游取到資訊後,根據 Binlog 資訊,使用 BMQ(位元組跳動自研的雲原生訊息佇列引擎) 也就是訊息中介軟體產品,將資料實時傳輸到流批一體計算引擎 Flink 中,進行流式處理或批式處理後,將整個資料 更新到 Iceberg 資料湖。資料湖的儲存底座也是位元組跳動自研的儲存底座——大資料檔案儲存(CloudFS)。

為什麼選擇 Flink

我們為什麼會選擇 Flink 作為流批一體的計算引擎呢?

主要原因在於,Flink 是一個面向有限流和無限流有狀態計算的分散式計算框架,它能夠支援流處理和批處理兩種應用型別。

在傳統意義上,Flink 是一個無限的資料流。但如果我們用一個個的時間視窗把無限的資料流進行切分,我們就得到很多有限資料流,對 Flink 來說,批式資料只是流式資料的一種特例。

無論是無限資料流還是有限處理流,Flink 都可以通過同一種 API、同一套程式碼進行處理之後,服務下游的資料。這樣的流程也可以極大地減少工程師的學習和維護成本。

可以說,Flink 無論是從上層的程式碼層面、SDK 層面、API 層面,還是下層的排程器層面,都是針對流批一體的整體架構來進行設計的,是可以從上至下完整地支援流批一體的資料處理引擎。

Flink 流批一體架構

推薦系統流批一體實踐

下面以位元組跳動的推薦系統為例,向大家闡述位元組跳動內部使用流批一體的典型實踐。

推薦系統在位元組跳動佔據著重要的位置。今日頭條的新聞、抖音的視訊,每一條資訊流都需要由推薦系統進行推薦。如前文所述,整個推薦系統每天承載著龐大的推薦任務量和資料量。

在推薦系統的整個資料處理鏈路中,流式處理和批式處理都佔據著重要的位置。尤其是在特徵計算模組,推薦系統需要為使用者實時地推薦資訊流,保證實時性和準確性,同時也需要進行模型訓練以提升推薦準確性。雙資料鏈路的設計帶來了諸多問題。

雙鏈路存在的核心問題

推薦系統資料鏈路抽象圖

在流式鏈路中,我們接收使用者請求,獲得使用者的實時線上特徵,這些實時線上特徵經過實時的流式處理之後,再結合線上特徵庫,就可以得到一個比較龐大的特徵組。隨後,將整個特徵組輸入到線上預測模型中,就可以得到預測的結果,從而實時地為使用者推薦資訊流。

同時,這些特徵也會被存入離線儲存(如 HDFS)中,後續會利用這些特徵進行線下的批式模型訓練。對於離線訓練來說,存入 HDFS 中的資料,經過批式的 ETL 處理後,輸入到離線的模型訓練中,訓練出的模型可以用於更新線上服務的模型,從而更準確地服務使用者。

然而,正如上文所述,推薦系統的資料鏈路分了線上和離線兩個體系,所以推薦系統在計算和使用線上特徵和離線特徵時,需要分別使用兩種不同計算引擎和儲存進行在、離線特徵處理,帶來了以下問題:

  • 對流處理和批處理分別維護兩套程式碼,業務成本過高

  • 特徵回溯難度大

  • 如何使用歷史資料初始化狀態難定義

  • 資料不統一,儲存成本高

Flink SQL 實現計算一體

針對這些業務困境和核心問題,我們使用了 Flink SQL 去實現整個計算的流批一體。在整個資料處理鏈路中,我們基於 Flink 引擎,使用 Flink SQL 的方式同時處理流式任務和批式任務,由此可以達到:

  • 同時支援 Unbounded、Bounded 資料來源

  • 支援 Join 和 Union

  • 流批一體的執行模式

  • 自定義統一 Sink Connectors

通過 Flink SQL 實現流批一體後,整個資料鏈路在計算的速度、特徵的迭代,及業務降本增效上都取得了極大的成果。主要原因在於使用 Flink SQL 實現流批一體後:

  • 同一份程式碼既可以實時計算,又可以批式計算

  • 節省開發成本,加速特徵迭代過程

如上圖所示,推薦系統中的特徵需要定期回溯並用以更新推薦模型,保證線上推薦的準確性。使用 Flink SQL 實現了流批計算一體後,我們可以用同一套程式碼去進行實時計算和批式計算,批式計算可以使用與實時計算同樣的程式碼進行歷史資料的回溯,這就保證了資料一致。

Iceberg 實現儲存一體

在儲存方面,我們選用了 Iceberg 作為統一的儲存格式。如下圖所示,特徵資料經過位元組跳動自研的訊息佇列引擎 BMQ 統一地流入 Flink 引擎,在 Flink SQL 進行處理之後,再 Upsert 到整個資料庫當中,進行統一的管理。

基於 Iceberg 實現特徵的統一儲存,具備以下能力:

  • 儲存流批一體,支援元資料的更新和管理

  • 提供 ACID 保證和快照功能

  • 併發讀寫

  • 計算儲存引擎解耦

  • Arrow 向量化資料傳輸

  • 小檔案 Compaction

優化收益

從整體業務收益來看,採用 Flink + Iceberg 的流批一體架構後,取得了較為明顯的降本增效效果:

  • 維護一套資料處理程式碼,人力成本大幅降低

  • 特徵儲存成本降低 40% 以上

  • Arrow 資料傳輸進行特徵訓練,CPU 消耗降低 13%,網路 IO 降低 40%

雲原生計算流批一體解決方案

雲原生計算團隊將位元組跳動內部流批一體方案進行整合優化後,輸出了雲原生計算平臺——一個開箱即用的、基於 Kubernets 的大資料 & AI 開發平臺。

雲原生計算平臺部署靈活,既能以火山引擎的公有云為底座,也能以專有云及其他的 Kubernets 底座進行部署。

在火山引擎資源底座的基礎之上,我們還提供豐富的資源排程策略、自動化流水線的 CICD 交付,以及豐富的資源管理、資料管理、作業管理等功能。

雲原生計算平臺架構

在此之上,是位元組跳動流批一體解決方案的核心引擎。

首先是流批一體的儲存。流批一體儲存主要是由兩部分組成,一部分是火山引擎自研的大資料統一儲存 CloudFS——作為整個儲存層和資料加速層為上游的引擎提供服務。另一部分是 Iceberg,我們以 Iceberg 為儲存層,利用上層的 Table Format 進行元資料資訊的管理。與此同時,通過對資料和源資料的操作,增加整個資料流資料的管控性和流轉速度。

其次是三款計算引擎。

  • Flink 實時計算引擎。我們在整個鏈路中會把 Flink 作為流批一體的引擎。

  • Spark 批式計算引擎。Spark 其實也是一款流批一體的計算引擎,在批式計算有它獨特的優勢。

  • Ray 動態引擎。Ray 動態引擎相對較新。我們用整個 Ray 動態引擎來做資源的極致擴縮、極致彈性,服務資料探勘場景。

  • 在三款主要的計算引擎之外,還有位元組跳動自研的雲原生訊息引擎 BMQ,及開放搜尋引擎 Open Search。

通過這五款引擎,我們打造了一個端到端的資料鏈路——資料存入大資料統一檔案儲存(CloudFS)之後,經由不同的引擎進行處理,服務上層業務。

平臺管控臺 UI 大資料開發平臺統一管理資料處理過程,同時整個雲原生計算平臺生態開放,可以對接各種大資料開發平臺以及 AI 開發的 Studio IDE。

最上層是應用層。由主引擎及儲存組成的流批一體解決方案,可以形成資料視覺化、安全及金融風控、資料化運營等解決方案,端到端地服務數字營銷,實時大屏、車聯網等業務場景。

總的來說,在雲原生計算平臺流批一體解決方案中,我們選擇了 Flink 作為流批一體的計算引擎,CloudFS 和 Iceberg 作為流批一體的統一儲存,服務機器學習場景和資料處理場景,無論是位元組內部的推薦系統,還是對外部提供服務,都能夠針對這兩種場景提供完備的服務。

當前,雲原生計算平臺旗下公有云產品流式計算 Flink 版大資料檔案儲存CloudFS)都在免費公測中,掃碼直達官網,歡迎申請試用:

流式計算 Flink 版

大資料檔案儲存(CloudFS)

此外,雲原生計算平臺部署靈活支援公有云混合雲及多雲部署,全面貼合企業上雲策略,瞭解更多混合雲資訊,歡迎聯絡雲原生計算小助手: