Streaming Data Warehouse 儲存:需求與架構

danny_2018發表於2022-11-11

一、數倉中的計算

在計算機領域,資料倉儲(DW 或 DWH),是一個用於報告和資料分析的系統,被認為是商業智慧的一個核心組成部分。它將當前和歷史資料儲存在一個地方,為整個企業的工作人員建立分析報告。

典型的基於提取、轉換、載入(ETL)的資料倉儲使用 ODS 層、DWD 層和 DWS 層來容納其關鍵功能。資料分析師可以靈活的查詢 (Query) 數倉中的每一層,獲取有價值的商業資訊。

數倉中有三個關鍵指標:

資料的新鮮度:資料從產生開始,到在倉庫中經過一系列處理後可供使用者查詢所經過的時間長度。通常 ETL 就是用來準備資料的一系列過程,ETL 更多是透過排程執行一系列流計算或者批計算的作業來完成。

資料的查詢延時:資料準備好後,使用者透過 Query 查詢表中的資料,從使用者發出查詢到收到查詢結果的時間長度為查詢延時。查詢延時直接決定了終端使用者的體感。

成本:完成一定量的資料分析(包括 ETL 和查詢等各類計算)需要的資源量。成本也是數倉中的一個關鍵指標。

這三個指標的關係是什麼呢?

企業需要在控制成本的情況下,能達到更好的查詢延時和新鮮度。不同的資料可能有不同的成本要求。

新鮮度和查詢延時在某些情況也是此消彼長的關係,比如使用更長時間來準備資料、清洗和預處理資料,查詢會更快。

所以這三者構成了數倉中的一個三角 Tradeoff[2]:

(注:三角中,離頂點更近代表更好,離頂點更遠代表更差)

對於這個三角 Tradeoff,業界目前的主流架構有著怎麼樣的取捨呢?

二、業界主流架構

典型的離線數倉:

離線數倉使用 Batch ETL 基於分割槽粒度來覆寫 (INSERT OVERWRITE),在解決超大資料的場景的同時,有著很好的成本控制。

但是它有兩個比較嚴重的問題:

新鮮度差:資料延時一般是 T + 1,即業務上當天產生的資料需要第二天才能查詢到。

不擅長處理更新流 (Changelog),離線數倉裡面儲存的都是 Append 資料,如果需要接收類似資料庫變更日誌的更新流,需要反覆的合併全量資料和增量資料,成本激增。

為了解決上述問題,實時數倉逐漸興起,一個典型的實時數倉實現是使用 Flink + Kafka 的方案構建中間層,最終寫到線上資料庫或分析系統中,達到秒級的全鏈路延時,有著非常好的資料新鮮度。

但是,它也逐漸暴露出一些問題。

問題一,中間層不可查

存在 Kafka 中的資料查詢受限,無法靈活的進行 OLAP 查詢,通常也沒有儲存長期歷史資料。這與廣泛使用的數倉有很大不同,在一個成熟的 Warehouse 體系中,數倉中的每一個資料集都應該是可供查詢的 Table 抽象,而 Kafka 無法滿足使用者對於 Table 抽象的所有需求,比如說:

查詢能力受限。實時數倉架構要求所有可供查詢的資料集被預先計算,並且最終寫入可供查詢的分析系統,但實際業務中不是所有計算都可以預先定義的,資料分析師的大量需求是臨時的 Ad hoc 查詢,如果中間資料 Queue 不可查,這會嚴重限制業務的資料分析能力。

問題排查困難。實時數倉中,如果資料有問題,使用者需要排查資料 Pipeline,但由於儲存中間結果的 Queue 不可查,導致排查難度非常高。

綜上,我們希望能有統一的架構得到一個處處可查詢的實時數倉,而不是中間結果被管道化的數倉。

問題二,實時鏈路成本高

天下沒有免費的午餐,搭建一條實時鏈路是比較昂貴的。

儲存成本:不管是 Kafka 還是後面的 ADS 層,它們都是線上服務,雖然有很低的延時,但是有很高的儲存成本。

遷移和維護成本:實時鏈路是與獨立於離線的新的一套系統,並不相容離線的一套工具鏈,遷移和維護成本都很大。

由此,我們希望能有一個低成本的實時數倉,它提供低執行成本併相容離線工具鏈,同時加速原有的離線數倉。

總結:

因為當前的兩套架構面向不同的取捨和場景,所以業務通常只能維護兩套架構,甚至需要不同的技術團隊,這不僅在帶來了很大的資源成本,也帶來了昂貴的開發成本和運維成本。

那麼我們是不是有可能提供一個在新鮮度、查詢延時、查詢能力和成本等各方面比較均衡的數倉呢?為了回答這個問題,我們需要分析新鮮度和查詢延時背後的技術原理,不同的 Tradeoff 導致的不同架構,以及它們背後的技術差異。

三、ETL 新鮮度

首先需要思考的是資料的新鮮度:資料的新鮮度衡量的是資料從產生開始,到在倉庫中經過一系列處理後可供使用者查詢所經過的時間長度。資料被攝入到數倉裡,並且經過一系列 ETL 的處理後,資料才進入可用的狀態。

傳統的批計算是按照口徑來進行 ETL 計算的,所以它的新鮮度是:口徑 + ETL延時。一般的口徑是天,所以傳統離線數倉的新鮮度最少也是一天。按照口徑來計算,計算的輸入和輸出是全量的。如果新鮮度要小於口徑,計算的輸入和輸出是部分的,也就是增量的。典型的增量計算就是流計算,比如 Flink Streaming。

增量計算也不完全等同於流計算,比如也可以有小批次的增量計算。全量計算不完全等同於批計算,比如流計算也可以做 Window 來全量的輸出 (也就是說流計算的延遲也可以很大,這樣可以降低成本);

四、Query Latency

查詢延時會直接影響資料分析效率和體驗,查詢是返回給人看的,這個人不是機器人,他看到的資料是經過過濾或者聚合後的資料。在傳統離線數倉中,查詢大表往往可能需要 10+ 分鐘的時間。

加速查詢的返回最直觀的方式是預計算,本質上數倉的 ETL 就是在做預計算的事情,資料分析人員查詢的計算需要的時間太久時,他會通知數倉人員,建立對應的 ETL Pipeline,資料準備好後,分析人員直接查詢最終結果表即可。從一個角度上看,這其實是在用新鮮度換取更快的查詢延時。

但是在傳統離線數倉中,有大量的即席查詢(Ad Hoc),使用者根據自己的需求,靈活的選擇查詢條件。有大表參與的查詢往往可能需要 10+ 分鐘的時間,為了儘快的返回結果,各大儲存系統使用了各種各樣的最佳化手段。

比如儲存更靠近計算,越靠近計算,讀取越快:

一些 Message Queue 和 OLAP 系統,它們只提供本地磁碟的儲存,這保證了讀取效能,但是也犧牲了靈活性,擴容和遷移代價比較大,成本也更高。

另一個方向是計算儲存分離的架構,資料全在遠端,但是透過本地的 Cache,來減小遠端訪問 DFS /Object Store 的高昂代價。

比如 Data Skipping,結合查詢的條件和欄位,跳過不相關的資料來加速資料的查詢:

Hive:透過分割槽裁剪查詢特定分割槽,透過列存跳過不相關的欄位。

湖儲存:在使用列存的基礎上,引入檔案的統計資訊,根據檔案的統計資訊來儘量減少一些檔案的不必要讀取。

OLAP 系統:在使用列存的基礎上,比如使用 LSM 結構來讓資料儘可能按照主鍵有序,有序是最利於查詢的結構之一,比如 Clickhouse。

KV 系統:透過資料的組織結構,使用 LSM 的結構來加速查詢。

Message Queue:Queue 其實是透過一種特殊的讀取介面來達到快速定位資料的能力,它只提供基於 Offset / Timestamp 的定位方式來接著增量讀取資料。

還有很多最佳化手段,這裡不一一列舉了,儲存透過各種手段來配合計算加速查詢,讓查詢找得快、讀得快。

透過上述的分析,我們可以看到,不同系統底層的技術基本都是相通的:

流計算和批計算是計算的不同模式,它們都可以完成全量計算或者增量計算。

儲存加速查詢效能的手段都是圍繞著找得快和讀得快,底層的原理是相通的。

理論上來說,我們應該有可能透過底層技術的某種選擇和組合搭建某種架構,來達到我們想要的 Tradeoff。這個統一的架構可能需要根據不同的 Tradeoff 解決以下場景:

實時數倉:新鮮度很好。

近實時數倉:作為離線數倉的加速,在不帶來太高昂的成本情況下,提高新鮮度。

離線數倉:有著比較好的成本控制。

離線 OLAP:加速數倉的某一部分的查詢效能,比如 ADS 表。

Streaming Warehouse 的目標是成為一個統一的架構:

(注:三角中,離頂點更近代表更好,離頂點更遠代表更差)

一個理想的數倉應該是使用者可以隨意調整成本、新鮮度、查詢延時之間的 Tradeoff,這要求數倉能完全覆蓋離線數倉、實時數倉、OLAP 的全部能力。Streaming Data Warehouse 在實時數倉的基礎上往前走了一步,大幅降低了實時數倉的成本。

Streaming DW 在提供實時計算能力的同時,可以讓使用者在同套架構下覆蓋離線數倉的能力。使用者可以根據業務的需求作出相應的 Tradeoff,解決不同場景的問題。

五、Streaming Data Warehouse

在具體看 Streaming Data Warehouse 的儲存架構是如何設計之前,我們先來回顧一下之前提到的主流實時數倉的兩個問題。解決了這兩個問題,Streaming Data Warehouse 的架構設計也就呼之欲出了。

5.1 中間資料不可查

既然中間的 Kafka 儲存不可查,一個實時離線一體化的想法是:實時離線一比一雙跑,業務層去做盡可能多的封裝,儘量讓使用者看到一套表的抽象。

許多使用者都會使用 Flink 加 Kafka 做實時資料流處理,將分析結果寫入線上服務層對使用者進行展示或進一步分析,與此同時將實時數倉中 Kafka 的資料匯入到後臺的非同步離線數倉,對實時資料進行補充,每天定期大規模的批次執行/全量執行或對歷史資料定期修正。

但這個架構存在著幾個問題:

Table 的抽象不同:採用不同的技術棧,實時鏈路跟離線鏈路有兩套 Table 抽象,不但增加了開發成本,而且降低了開發效率;業務層儘可能的去封裝,但是總會遇到各種磕磕碰碰的問題,有不少不對齊的坑。

實時數倉和離線數倉的資料口徑難以保持天然的一致性;

在 Streaming Data Warehouse 中,我們希望數倉有面向查詢統一的 Table 抽象,所有流動中的資料皆可分析,沒有資料盲點。這就要求這個統一的 Table 抽象能夠同時支援兩種能力:

Message Queue

OLAP 查詢

也就是說在同一個 Table 上,使用者可以以訊息佇列的方式訂閱這個 Table 上的 Change Log,也可以對這個 Table 直接進行 OLAP 查詢。

下面我們再來看經典實時數倉的第二個問題。

5.2 實時鏈路成本高

雖然 Streaming Data Warehouse 提供的統一 Table 抽象能夠很好的解決新鮮度和查詢延遲的問題,但相較於離線數倉其成本是更高的。在很多時候並非所有的業務場景都對新鮮度和查詢延時有很高的要求,因此提供低成本 Table 儲存能力依然是必要的。

這裡湖儲存是一個不錯的選擇:

湖儲存的儲存成本更低:湖儲存基於 DFS / Object Store,無 Service,資源和運維成本都更低。

湖儲存的區域性更新靈活:歷史分割槽有問題怎麼辦?需要訂正怎麼辦?湖儲存的計算成本更低,湖儲存 + 離線 ETL,INSERT OVERWRITE 訂正歷史分割槽,比實時更新成本低很多。

湖儲存的開放性:湖儲存可以開放給各種批計算引擎。

因此,Streaming Data Warehouse在保持全鏈路資料實時流動的同時,還需要同時提供低成本的離線儲存,並且做到架構不影響實時鏈路。由於通常來說實時鏈路的 SLA 要求比離線鏈路要高,因此 Streaming Data Warehouse 的儲存在設計和實現上要把 Queue 的寫入和消費作為高優先順序,對歷史資料的儲存不應該影響其作為 Queue 的能力。

六、Flink Table Store

Flink Table Store正是專門為 Streaming Warehouse 打造的流批一體儲存。

在過去的幾年裡,在我們眾多貢獻者和使用者的幫助下,Apache Flink 已經成為了最好的分散式計算引擎之一,特別是在大規模的有狀態流處理方面。儘管如此,當大家試圖從資料中實時獲得洞察力時,仍然面臨著一些挑戰。在這些挑戰中,一個突出的問題是缺乏能滿足所有計算模式的儲存。

到現在為止,人們為不同的目的部署一些與 Flink 一起協同的儲存系統是很常見的。一個典型的做法是部署一個用於流處理的訊息佇列,一個用於批處理和 Ad-Hoc 查詢的可掃描檔案系統/物件儲存,以及一個用於點查的 KV 儲存。由於其複雜性和異構性,這樣的架構在資料質量和系統維護方面都存在挑戰。這已經成為了一個損害 Apache Flink 帶來的流和批處理統一的端到端使用者體驗的主要問題。

Flink Table Store 的目標就是要解決上述問題。這對 Flink 來說是重要的一步,它將 Flink 的能力從計算領域擴充套件到了儲存領域。也正因為這樣,我們可以為使用者提供更好的端到端體驗。

6.1 架構

■ 6.1.1 Service

Coordinator 是叢集的管控節點,它主要負責管理各 Executors,主要能力有:

Coordinator 管理 Executors 的生命週期,客戶端透過 Coordinator 尋找 Executors 的地址。

Data Manager:

管理 Table 的版本,負責與 Metastore 打交道,定期將版本 checkpoint 到 metastore 裡。

根據寫入的資料和查詢的 Pattern,管理快取、管理索引。

Resource Manager:

管理 Table 的 Buckets 在 Executors 的分佈。

根據需要動態的分配 Buckets 到 Executors 上。

Metastore 是個抽象的節點,它可以對接 Hive Metastore,也可以最小化依賴基於 Filesytem,也可以對接你自己的 Metastore,它儲存了最基本的表資訊。你不用擔心效能問題,更詳細的複雜的表資訊放在了湖儲存裡。

Executor 是一個單獨的計算節點,作為儲存的一個 Cache 和本地計算的加速單元:

它負責接收資料的更新,寫入本地 Cache、寫入本地磁碟、再 Flush 到底層的 DFS 中。

它也面向實時的 OLAP 查詢和 Queue 的消費,執行一些加速的本地計算。

每個 Executor 負責一個或多個 Buckets,每個 Bucket 有對應的 Changelog,這些 Changelog 會儲存在 Message Queue 裡,主要用作:

Write ahead log,Executor Failover 後讀取 log 來恢復資料。

提供 Queue 的抽象,提供 Table 的 Changelog 流消費給下游的流計算。

■ 6.1.2 湖儲存

Executor 的資料經過了 Checkpoint 後就落入了湖儲存中,湖儲存建立在列存的檔案格式和共享 DFS 儲存上。湖儲存提供完整的 Table Format 抽象,它的主要目的是以較低的成本支撐更新和讀取:

LSM 結構:用於大量的資料更新和高效能的查詢。

Columnar File Format:使用 Apache ORC 來支援高效查詢。

Lake Storage:後設資料和資料在 DFS 和 Object Store 上。

■ 6.1.3 冷熱分離

儲存的讀寫路徑被分為了兩條:

Streaming Pipeline & Online OLAP Query:透過 Coordinator 獲取後設資料,從 Executor 裡寫入和獲取資料。

Batch Pipeline & Offline Query:透過 Metastore 獲取後設資料,從湖儲存中寫入和獲取資料。

Service 的資料是最新的,經過了分鐘級的 Checkpoint 後同步到了湖儲存中。所以使用者讀取湖儲存只會讀取到沒那麼及時的資料,本質上,兩邊的資料是一致的。

Service 和湖儲存的使用有這些區別:

Service 適合最新的熱資料,提供快速的逐條 Update 寫入,高效能的查詢延時。

Service 不適合 Offline Query,一個是影響 Online 穩定性,另一個是成本會更高。

Service 不支援 Batch Pipeline 的 INSERT OVERWRITE。

所以儲存需要暴露湖儲存來承擔這些能力,那業務上如何判斷哪些資料是在 Service 裡操作,哪些資料在湖儲存裡操作呢?

只有 ARCHIVE 後的分割槽才能在湖儲存中進行 Batch 的 INSERT OVERWRITE。

使用者在建立表時可以指定分割槽自動 ARCHIVE 時間。

也可以透過 DDL 語句顯式的歸檔某個分割槽。

6.2 短期目標

■ 6.2.1 短期架構

Streaming Data Warehouse 的整體變革是巨大的,OLAP、Queue、湖儲存、流計算、批計算,每一個領域都有佼佼者在其中發力,今天還不可能短期內產出一個完整的解決方案。

但是,我們在前進,在 Apache Flink Table Store 中,我們首先開發了基於 LSM 的湖儲存,並原生整合了 Kafka 作為 Log System。

相比於上述章節的完整架構,短期的架構沒有 Coordinator 和 Excutors,這意味著它:

不能提供實時 OLAP 的能力,基於檔案的 OLAP 只能是準實時的延時。

沒有服務化資料管控的能力。

我們希望從底層做起,夯實基礎,首先提出一個完整的統一抽象,再在儲存上做加速能力,再提供真實時的 OLAP。

目前的架構它提供兩個核心價值:

■ 6.2.2 價值一:實時中間層可查

Table Store 給原有實時數倉的 Kafka 分層儲存帶來查詢的能力,中間資料可查;

Table Store 仍然具有流式實時 Pipeline 的能力,它原生 Log 整合,支援整合 Kafka,遮蔽掉流批的概念,使用者只看到 Table 的抽象。

但是值得注意的是,資料寫入儲存不應該影響原有寫入 Kafka 的穩定性,這點是需要加強和保證的。

■ 6.2.3 價值二:離線數倉加速

Table Store 加速離線數倉,相容 Hive 離線數倉的同時,提供增量更新的能力。

Table Store 提供完善的湖儲存 Table Format,提供準實時 OLAP 查詢,LSM 的結構不但有利於更新效能,也可以有更好的 Data Skipping,加速 OLAP 查詢。

6.3 後續計劃

社群目前正在努力加強核心功能,穩定儲存格式,並補全剩餘的部分,使 Flink Table Store 為生產做好準備。

在即將釋出的 0.2.0 版本中,我們希望可以提供流批一體的 Table Format,逐漸完善的流批一體湖儲存,你可以期待(至少)以下的額外功能:

支援 Apache Hive 引擎的 Flink Table Store Reader。

支援調整 Bucket 的數量。

支援 Append Only 資料,Table Store 不只是限於更新場景。

完整的 Schema Evolution,更好的後設資料管理。

根據 0.1.0 預覽版的反饋進行改進。

在中期,你也可以期待:

支援 Presto、Trino 和 Apache Spark 的 Flink Table Store Reader。

Flink Table Store Service,以加速更新和提高查詢效能,擁有毫秒級的 Streaming Pipeline 能力,和較強的 OLAP 能力。

請試一試 0.1.0 預覽版,在 Flink 郵件列表中分享您的反饋,併為專案作出貢獻。

6.4 專案資訊

Apache Flink Table Store 專案[4]正在開發中,目前已經發布了第一個版本,歡迎大家試用和反饋。

來自 “ Flink實戰剖析 ”, 原文作者:Flink實戰剖析;原文連結:https://view.inews.qq.com/k/20220620A0915X00?web_channel=wap&openApp=false,如有侵權,請聯絡管理員刪除。

相關文章