數據湖方案:Hudi、Delta、Iceberg深度對比

目前市面上流行的三大開源數據湖方案分別爲:delta、Apache Iceberg和Apache Hudi。

 

其中,由於Apache Spark在商業化上取得巨大成功,所以由其背後商業公司Databricks推出的delta也顯得格外亮眼。

 

Apache Hudi是由Uber的工程師爲滿足其內部數據分析的需求而設計的數據湖項目,它提供的fast upsert/delete以及compaction等功能可以說是精準命中廣大人民羣衆的痛點,加上項目各成員積極地社區建設,包括技術細節分享、國內社區推廣等等,也在逐步地吸引潛在用戶的目光。

 

Apache Iceberg目前看則會顯得相對平庸一些,簡單說社區關注度暫時比不上delta,功能也不如Hudi豐富,但卻是一個野心勃勃的項目,因爲它具有高度抽象和非常優雅的設計,爲成爲一個通用的數據湖方案奠定了良好基礎。

 

很多用戶會想,看着三大項目異彩紛呈,到底應該在什麼樣的場景下,選擇合適數據湖方案呢?今天我們就來解構數據湖的核心需求,深度對比三大產品,幫助用戶更好地針對自身場景來做數據湖方案選型。

 

首先,我們來逐一分析爲何各技術公司要推出他們的開源數據湖解決方案,他們碰到的問題是什麼,提出的方案又是如何解決問題的。我們希望客觀地分析業務場景,來理性判斷到底哪些功能纔是客戶的痛點和剛需。

 

Databricks和Delta

 

以Databricks推出的delta爲例,它要解決的核心問題基本上集中在下圖 :

 

 

圖片來源:https://www.slideshare.net/databricks/making-apache-spark-better-with-delta-lake

 

在沒有delta數據湖之前,Databricks的客戶一般會採用經典的lambda架構來構建他們的流批處理場景。

 

以用戶點擊行爲分析爲例,點擊事件經Kafka被下游的Spark Streaming作業消費,分析處理(業務層面聚合等)後得到一個實時的分析結果,這個實時結果只是當前時間所看到的一個狀態,無法反應時間軸上的所有點擊事件。

 

所以爲了保存全量點擊行爲,Kafka還會被另外一個Spark Batch作業分析處理,導入到文件系統上(一般就是parquet格式寫HDFS或者S3,可以認爲這個文件系統是一個簡配版的數據湖),供下游的Batch作業做全量的數據分析以及AI處理等。

 

這套方案其實存在很多問題  : 

 

第一、批量導入到文件系統的數據一般都缺乏全局的嚴格schema規範,下游的Spark作業做分析時碰到格式混亂的數據會很麻煩,每一個分析作業都要過濾處理錯亂缺失的數據,成本較大。

 

第二、數據寫入文件系統這個過程沒有ACID保證,用戶可能讀到導入中間狀態的數據。所以上層的批處理作業爲了躲開這個坑,只能調度避開數據導入時間段,可以想象這對業務方是多麼不友好;同時也無法保證多次導入的快照版本,例如業務方想讀最近5次導入的數據版本,其實是做不到的。

 

第三、用戶無法高效upsert/delete歷史數據,parquet文件一旦寫入HDFS文件,要想改數據,就只能全量重新寫一份的數據,成本很高。事實上,這種需求是廣泛存在的,例如由於程序問題,導致錯誤地寫入一些數據到文件系統,現在業務方想要把這些數據糾正過來;線上的MySQL binlog不斷地導入update/delete增量更新到下游數據湖中;某些數據審查規範要求做強制數據刪除,例如歐洲出臺的GDPR隱私保護等等。

 

第四、頻繁地數據導入會在文件系統上產生大量的小文件,導致文件系統不堪重負,尤其是HDFS這種對文件數有限制的文件系統。

 

所以,在Databricks看來,以下四個點是數據湖必備的:

 

 

事實上,  Databricks在設計delta時,希望做到流批作業在數據層面做到進一步的統一(如下圖)。業務數據經過Kafka導入到統一的數據湖中(無論批處理,還是流處理),上層業務可以藉助各種分析引擎做進一步的商業報表分析、流式計算以及AI分析等等。

 

 

所以,總結起來,我認爲databricks設計delta時主要考慮實現以下核心功能特性:

 

 

Uber和Apache Hudi

 

Uber的業務場景主要爲:將線上產生的行程訂單數據,同步到一個統一的數據中心,然後供上層各個城市運營同事用來做分析和處理。

 

在2014年的時候,Uber的數據湖架構相對比較簡單,業務日誌經由Kafka同步到S3上,上層用EMR做數據分析;線上的關係型數據庫以及NoSQL則會通過ETL(ETL任務也會拉去一些Kakfa同步到S3的數據)任務同步到閉源的Vertica分析型數據庫,城市運營同學主要通過Vertica SQL實現數據聚合。當時也碰到數據格式混亂、系統擴展成本高(依賴收Vertica商業收費軟件)、數據回填麻煩等問題。

 

後續遷移到開源的Hadoop生態,解決了擴展性問題等問題,但依然碰到Databricks上述的一些問題,其中最核心的問題是無法快速upsert存量數據。

 

 

如上圖所示,ETL任務每隔30分鐘定期地把增量更新數據同步到分析表中,全部改寫已存在的全量舊數據文件,導致數據延遲和資源消耗都很高。

 

此外,在數據湖的下游,還存在流式作業會增量地消費新寫入的數據,數據湖的流式消費對他們來說也是必備的功能。所以,他們就希望設計一種合適的數據湖方案,在解決通用數據湖需求的前提下,還能實現快速的upsert以及流式增量消費。

 

 

Uber團隊在Hudi上同時實現了Copy On Write和Merge On Read的兩種數據格式,其中Merge On Read就是爲了解決他們的fast upsert而設計的。

 

簡單來說,就是每次把增量更新的數據都寫入到一批獨立的delta文件集,定期地通過compaction合併delta文件和存量的data文件。同時給上層分析引擎提供三種不同的讀取視角:僅讀取delta增量文件、僅讀取data文件、合併讀取delta和data文件。滿足各種業務方對數據湖的流批數據分析需求。

 

最終,我們可以提煉出Uber的數據湖需求爲如下圖,這也正好是Hudi所側重的核心特性:

 

 

Netflix和Apache Iceberg

 

Netflix的數據湖原先是藉助Hive來構建,但發現Hive在設計上的諸多缺陷之後,開始轉爲自研Iceberg,並最終演化成Apache下一個高度抽象通用的開源數據湖方案。

 

Netflix用內部的一個時序數據業務的案例來說明Hive的這些問題,採用Hive時按照時間字段做partition,他們發現僅一個月會產生2688個partition和270萬個數據文件。他們執行一個簡單的select查詢,發現僅在分區裁剪階段就耗費數十分鐘。

 

 

他們發現Hive的元數據依賴一個外部的MySQL和HDFS文件系統,通過MySQL找到相關的parition之後,需要爲每個partition去HDFS文件系統上按照分區做目錄的list操作。在文件量大的情況下,這是一個非常耗時的操作。

 

同時,由於元數據分屬MySQL和HDFS管理,寫入操作本身的原子性難以保證。即使在開啓Hive ACID情況下,仍有很多細小場景無法保證原子性。另外,Hive Metastore沒有文件級別的統計信息,這使得filter只能下推到partition級別,而無法下推到文件級別,對上層分析性能損耗無可避免。

 

最後,Hive對底層文件系統的複雜語義依賴,使得數據湖難以構建在成本更低的S3上。

 

於是,Netflix爲了解決這些痛點,設計了自己的輕量級數據湖Iceberg。在設計之初,作者們將其定位爲一個通用的數據湖項目,所以在實現上做了高度的抽象。

 

雖然目前從功能上看不如前面兩者豐富,但由於它牢固堅實的底層設計,一旦功能補齊,將成爲一個非常有潛力的開源數據湖方案。

 

總體來說,Netflix設計Iceberg的核心訴求可以歸納爲如下:

 

 

痛點小結

 

我們可以把上述三個項目針對的痛點,放到一張圖上來看。可以發現標紅的功能點,基本上是一個好的數據湖方案應該去做到的功能點:

 

 

七大維度對比

 

在理解了上述三大方案各自設計的初衷和麪向的痛點之後,接下來我們從7個維度來對比評估三大項目的差異。通常人們在考慮數據湖方案選型時,Hive ACID也是一個強有力的候選人,因爲它提供了人們需要的較爲完善功能集合,所以這裏我們把Hive ACID納入到對比行列中。

 

第一、ACID和隔離級別支持

 

 

這裏主要解釋下,對數據湖來說三種隔離分別代表的含義:

 

  • Serialization是說所有的reader和writer都必須串行執行;

  • Write Serialization: 是說多個writer必須嚴格串行,reader和writer之間則可以同時跑;

  • Snapshot Isolation: 是說如果多個writer寫的數據無交集,則可以併發執行;否則只能串行。Reader和writer可以同時跑。

 

綜合起來看,Snapshot Isolation隔離級別的併發性是相對比較好的。

 

第二、Schema變更支持和設計

 

 

這裏有兩個對比項,一個是schema變更的支持情況,我的理解是hudi僅支持添加可選列和刪除列這種向後兼容的DDL操作,而其他方案則沒有這個限制。另外一個是數據湖是否自定義schema接口,以期跟計算引擎的schema解耦。這裏iceberg是做的比較好的,抽象了自己的schema,不綁定任何計算引擎層面的schema。

 

第三、流批接口支持

 

 

目前Iceberg和Hive暫時不支持流式消費,不過Iceberg社區正在issue 179上開發支持。

 

第四、接口抽象程度和插件化

 

 

這裏主要從計算引擎的寫入和讀取路徑、底層存儲可插拔、文件格式四個方面來做對比。這裏Iceberg是抽象程度做得最好的數據湖方案,四個方面都做了非常乾淨的解耦。delta是databricks背後主推的,必須天然綁定spark;hudi的代碼跟delta類似,也是強綁定spark。

 

存儲可插拔的意思是說,是否方便遷移到其他分佈式文件系統上(例如S3),這需要數據湖對文件系統API接口有最少的語義依賴,例如若數據湖的ACID強依賴文件系統rename接口原子性的話,就難以遷移到S3這樣廉價存儲上,目前來看只有Hive沒有太考慮這方面的設計;文件格式指的是在不依賴數據湖工具的情況下,是否能讀取和分析文件數據,這就要求數據湖不額外設計自己的文件格式,統一用開源的parquet和avro等格式。這裏,有一個好處就是,遷移的成本很低,不會被某一個數據湖方案給綁死。

 

第五、查詢性能優化

 

 

第六、其他功能

 

 

這裏One line demo指的是,示例demo是否足夠簡單,體現了方案的易用性,Iceberg稍微複雜一點(我認爲主要是Iceberg自己抽象出了schema,所以操作前需要定義好表的schema)。做得最好的其實是delta,因爲它深度跟隨spark易用性的腳步。

 

Python支持其實是很多基於數據湖之上做機器學習的開發者會考慮的問題,可以看到Iceberg和Delta是做的很好的兩個方案。

 

出於數據安全的考慮,Iceberg還提供了文件級別的加密解密功能,這是其他方案未曾考慮到的一個比較重要的點。

 

第七、社區現狀(截止到2020-01-08)

 

 

這裏需要說明的是,Delta和Hudi兩個項目在開源社區的建設和推動方面,做的比較好。Delta的開源版和商業版本,提供了詳細的內部設計文檔,用戶非常容易理解這個方案的內部設計和核心功能,同時Databricks還提供了大量對外分享的技術視頻和演講,甚至邀請了他們的企業用戶來分享Delta的線上經驗。

 

Uber的工程師也分享了大量Hudi的技術細節和內部方案落地,研究官網的近10個PPT已經能較爲輕鬆理解內部細節,此外國內的小夥伴們也在積極地推動社區建設,提供了官方的技術公衆號和郵件列表週報。

 

Iceberg相對會平靜一些,社區的大部分討論都在Github的issues和pull request上,郵件列表的討論會少一點,很多有價值的技術文檔要仔細跟蹤issues和PR才能看到,這也許跟社區核心開發者的風格有關。

總結

 

我們把三個產品(其中delta分爲databricks的開源版和商業版)總結成如下圖:

 

 

如果用一個比喻來說明delta、iceberg、hudi、hive-acid四者差異的話,可以把四個項目比做建房子。由於開源的delta是databricks閉源delta的一個簡化版本,它主要爲用戶提供一個table format的技術標準,閉源版本的delta基於這個標準實現了諸多優化,這裏我們主要用閉源的delta來做對比。

 

 

Delta的房子底座相對結實,功能樓層也建得相對比較高,但這個房子其實可以說是databricks的,本質上是爲了更好地壯大Spark生態,在delta上其他的計算引擎難以替換Spark的位置,尤其是寫入路徑層面。

 

Iceberg的建築基礎非常紮實,擴展到新的計算引擎或者文件系統都非常的方便,但是現在功能樓層相對低一點,目前最缺的功能就是upsert和compaction兩個,Iceberg社區正在以最高優先級推動這兩個功能的實現。

 

Hudi的情況要相對不一樣,它的建築基礎設計不如iceberg結實,舉個例子,如果要接入Flink作爲Sink的話,需要把整個房子從底向上翻一遍,把接口抽象出來,同時還要考慮不影響其他功能,當然Hudi的功能樓層還是比較完善的,提供的upsert和compaction功能直接命中廣大羣衆的痛點。

 

Hive的房子,看起來是一棟豪宅,絕大部分功能都有,把它做爲數據湖有點像靠着豪宅的一堵牆建房子,顯得相對重量級一點,另外正如Netflix上述的分析,細看這個豪宅的牆面是其實是有一些問題的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章