Data Lake 三劍客——Delta、Hudi、Iceberg 對比分析


https://developer.aliyun.com/article/744920

簡介: 定性上講,三者均為 Data Lake 的數據存儲中間層,其數據管理的功能均是基於一系列的 meta 文件。meta 文件的角色類似於數據庫的 catalog/wal,起到 schema 管理、事務管理和數據管理的功能。

 

共同點

定性上講,三者均為 Data Lake 的數據存儲中間層,其數據管理的功能均是基於一系列的 meta 文件。meta 文件的角色類似於數據庫的 catalog/wal,起到 schema 管理、事務管理和數據管理的功能。與數據庫不同的是,這些 meta 文件是與數據文件一起存放在存儲引擎中的,用戶可以直接看到。這種做法直接繼承了大數據分析中數據對用戶可見的傳統,但是無形中也增加了數據被不小心破壞的風險。一旦某個用戶不小心刪了 meta 目錄,表就被破壞了,想要恢復難度非常大。

Meta 文件包含有表的 schema 信息。因此系統可以自己掌握 Schema 的變動,提供 Schema 演化的支持。Meta 文件也有 transaction log 的功能(需要文件系統有原子性和一致性的支持)。所有對表的變更都會生成一份新的 meta 文件,於是系統就有了 ACID 和多版本的支持,同時可以提供訪問歷史的功能。在這些方面,三者是相同的。

下面來談一下三者的不同。

Hudi

先說 Hudi。Hudi 的設計目標正如其名,Hadoop Upserts Deletes and Incrementals(原為 Hadoop Upserts anD Incrementals),強調了其主要支持 Upserts、Deletes 和 Incremental 數據處理,其主要提供的寫入工具是 Spark HudiDataSource API 和自身提供的 DeltaStreamer,均支持三種數據寫入方式:UPSERT,INSERT 和 BULK_INSERT。其對 Delete 的支持也是通過寫入時指定一定的選項支持的,並不支持純粹的 delete 接口。

其典型用法是將上游數據通過 Kafka 或者 Sqoop,經由 DeltaStreamer 寫入 Hudi。DeltaStreamer 是一個常駐服務,不斷地從上游拉取數據,並寫入 hudi。寫入是分批次的,並且可以設置批次之間的調度間隔。默認間隔為 0,類似於 Spark Streaming 的 As-soon-as-possible 策略。隨着數據不斷寫入,會有小文件產生。對於這些小文件,DeltaStreamer 可以自動地觸發小文件合並的任務。

在查詢方面,Hudi 支持 Hive、Spark、Presto。

在性能方面,Hudi 設計了 `
HoodieKey
,一個類似於主鍵的東西。
HoodieKey
有 Min/Max 統計,BloomFilter,用於快速定位 Record 所在的文件。在具體做 Upserts 時,如果 HoodieKey
不存在於 BloomFilter,則執行插入,否則,確認 HoodieKey
是否真正存在,如果真正存在,則執行 update。這種基於 HoodieKey + BloomFilter 的 upserts 方法是比較高效的,否則,需要做全表的 Join 才能實現 upserts。對於查詢性能,一般需求是根據查詢謂詞生成過濾條件下推至 datasource。Hudi 這方面沒怎么做工作,其性能完全基於引擎自帶的謂詞下推和 partition prune 功能。

Hudi 的另一大特色是支持 Copy On Write 和 Merge On Read。前者在寫入時做數據的 merge,寫入性能略差,但是讀性能更高一些。后者讀的時候做 merge,讀性能查,但是寫入數據會比較及時,因而后者可以提供近實時的數據分析能力。

最后,Hudi 提供了一個名為 run_sync_tool 的腳本同步數據的 schema 到 Hive 表。Hudi 還提供了一個命令行工具用於管理 Hudi 表。

hudi
image.png


Iceberg

Iceberg 沒有類似的 HoodieKey 設計,其不強調主鍵。上文已經說到,沒有主鍵,做 update/delete/merge 等操作就要通過 Join 來實現,而 Join 需要有一個 類似 SQL 的執行引擎。Iceberg 並不綁定某個引擎,也沒有自己的引擎,所以 Iceberg 並不支持 update/delete/merge。如果用戶需要 update 數據,最好的方法就是找出哪些 partition 需要更新,然后通過 overwrite 的方式重寫數據。Iceberg 官網提供的 quickstart 以及 Spark 的接口均只是提到了使用 Spark dataframe API 向 Iceberg 寫數據的方式,沒有提及別的數據攝入方法。至於使用 Spark Streaming 寫入,代碼中是實現了相應的 StreamWriteSupport,應該是支持流式寫入,但是貌似官網並未明確提及這一點。支持流式寫入意味着有小文件問題,對於怎么合並小文件,官網也未提及。我懷疑對於流式寫入和小文件合並,可能 Iceberg 還沒有很好的生產 ready,因而沒有提及(純屬個人猜測)。

在查詢方面,Iceberg 支持 Spark、Presto。

Iceberg 在查詢性能方面做了大量的工作。值得一提的是它的 hidden partition 功能。Hidden partition 意思是說,對於用戶輸入的數據,用戶可以選取其中某些列做適當的變換(Transform)形成一個新的列作為 partition 列。這個 partition 列僅僅為了將數據進行分區,並不直接體現在表的 schema 中。例如,用戶有 timestamp 列,那么可以通過 hour(timestamp) 生成一個 timestamp_hour 的新分區列。timestamp_hour 對用戶不可見,僅僅用於組織數據。Partition 列有 partition 列的統計,如該 partition 包含的數據范圍。當用戶查詢時,可以根據 partition 的統計信息做 partition prune。

除了 hidden partition,Iceberg 也對普通的 column 列做了信息收集。這些統計信息非常全,包括列的 size,列的 value count,null value count,以及列的最大最小值等等。這些信息都可以用來在查詢時過濾數據。

Iceberg 提供了建表的 API,用戶可以使用該 API 指定表明、schema、partition 信息等,然后在 Hive catalog 中完成建表。


Delta

我們最后來說 Delta。Delta 的定位是流批一體的 Data Lake 存儲層,支持 update/delete/merge。由於出自 Databricks,spark 的所有數據寫入方式,包括基於 dataframe 的批式、流式,以及 SQL 的 Insert、Insert Overwrite 等都是支持的(開源的 SQL 寫暫不支持,EMR 做了支持)。與 Iceberg 類似,Delta 不強調主鍵,因此其 update/delete/merge 的實現均是基於 spark 的 join 功能。在數據寫入方面,Delta 與 Spark 是強綁定的,這一點 Hudi 是不同的:Hudi 的數據寫入不綁定 Spark(可以用 Spark,也可以使用 Hudi 自己的寫入工具寫入)。

在查詢方面,開源 Delta 目前支持 Spark 與 Presto,但是,Spark 是不可或缺的,因為 delta log 的處理需要用到 Spark。這意味着如果要用 Presto 查詢 Delta,查詢時還要跑一個 Spark 作業。更為蛋疼的是,Presto 查詢是基於 SymlinkTextInputFormat。在查詢之前,要運行 Spark 作業生成這么個 Symlink 文件。如果表數據是實時更新的,意味着每次在查詢之前先要跑一個 SparkSQL,再跑 Presto。這樣的話為何不都在 SparkSQL 里搞定呢?這是一個非常蛋疼的設計。為此,EMR 在這方面做了改進,支持了 DeltaInputFormat,用戶可以直接使用 Presto 查詢 Delta 數據,而不必事先啟動一個 Spark 任務。

在查詢性能方面,開源的 Delta 幾乎沒有任何優化。Iceberg 的 hidden partition 且不說,普通的 column 的統計信息也沒有。Databricks 對他們引以為傲的 Data Skipping 技術做了保留。不得不說這對於推廣 Delta 來說不是件好事。EMR 團隊在這方面正在做一些工作,希望能彌補這方面能力的缺失。

Delta 在數據 merge 方面性能不如 Hudi,在查詢方面性能不如 Iceberg,是不是意味着 Delta 一無是處了呢?其實不然。Delta 的一大優點就是與 Spark 的整合能力(雖然目前仍不是很完善,但 Spark-3.0 之后會好很多),尤其是其流批一體的設計,配合 multi-hop 的 data pipeline,可以支持分析、Machine learning、CDC 等多種場景。使用靈活、場景支持完善是它相比 Hudi 和 Iceberg 的最大優點。另外,Delta 號稱是 Lambda 架構、Kappa 架構的改進版,無需關心流批,無需關心架構。這一點上 Hudi 和 Iceberg 是力所不及的。

delta
image.png


總結

通過上面的分析能夠看到,三個引擎的初衷場景並不完全相同,Hudi 為了 incremental 的 upserts,Iceberg 定位於高性能的分析與可靠的數據管理,Delta 定位於流批一體的數據處理。這種場景的不同也造成了三者在設計上的差別。尤其是 Hudi,其設計與另外兩個相比差別更為明顯。隨着時間的發展,三者都在不斷補齊自己缺失的能力,可能在將來會彼此趨同,互相侵入對方的領地。當然也有可能各自關注自己專長的場景,築起自己的優勢壁壘,因此最終誰贏誰輸還是未知之數。

下表從多個維度對三者進行了總結,需要注意的是此表所列的能力僅代表至 2019 年底。

· Delta Hudi Iceberg
Incremental Ingestion Spark Spark Spark
ACID updates HDFS, S3 (Databricks), OSS HDFS HDFS, S3
Upserts/Delete/Merge/Update Delete/Merge/Update Upserts/Delete No
Streaming sink Yes Yes Yes(not ready?)
Streaming source Yes No No
FileFormats Parquet Avro,Parquet Parquet, ORC
Data Skipping File-Level Max-Min stats + Z-Ordering (Databricks) File-Level Max-Min stats + Bloom Filter File-Level Max-Min Filtering
Concurrency control Optimistic Optimistic Optimistic
Data Validation Yes (Databricks) No Yes
Merge on read No Yes No
Schema Evolution Yes Yes Yes
File I/O Cache Yes (Databricks) No No
Cleanup Manual Automatic No
Compaction Manual Automatic No

作者:辛庸,阿里巴巴計算平台事業部 EMR 技術專家。Apache Hadoop,Apache Spark contributor。對 Hadoop、Spark、Hive、Druid 等大數據組件有深入研究。目前從事大數據雲化相關工作,專注於計算引擎、存儲結構、數據庫事務等內容。

注:限於本人水平,文中內容可能有誤,也歡迎讀者批評指正!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM