Data Lake 三劍客—Delta、Hudi、Iceberg 對(duì)比分析

本文來源于云棲社區(qū):https://yq.aliyun.com/articles/743514
作者:xy_xin

共同點(diǎn)

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

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

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

Hudi

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

其典型用法是將上游數(shù)據(jù)通過 Kafka 或者 Sqoop,經(jīng)由 DeltaStreamer 寫入 Hudi。DeltaStreamer 是一個(gè)常駐服務(wù),不斷地從上游拉取數(shù)據(jù),并寫入 hudi。寫入是分批次的,并且可以設(shè)置批次之間的調(diào)度間隔。默認(rèn)間隔為 0,類似于 Spark Streaming 的 As-soon-as-possible 策略。隨著數(shù)據(jù)不斷寫入,會(huì)有小文件產(chǎn)生。對(duì)于這些小文件,DeltaStreamer 可以自動(dòng)地觸發(fā)小文件合并的任務(wù)。

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

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

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

最后,Hudi 提供了一個(gè)名為 run_sync_tool 的腳本同步數(shù)據(jù)的 schema 到 Hive 表。Hudi 還提供了一個(gè)命令行工具用于管理 Hudi 表。

hudiimage

Iceberg

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

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

Iceberg 在查詢性能方面做了大量的工作。值得一提的是它的 hidden partition 功能。Hidden partition 意思是說,對(duì)于用戶輸入的數(shù)據(jù),用戶可以選取其中某些列做適當(dāng)?shù)淖儞Q(Transform)形成一個(gè)新的列作為 partition 列。這個(gè) partition 列僅僅為了將數(shù)據(jù)進(jìn)行分區(qū),并不直接體現(xiàn)在表的 schema 中。例如,用戶有 timestamp 列,那么可以通過 hour(timestamp) 生成一個(gè) timestamp_hour 的新分區(qū)列。timestamp_hour 對(duì)用戶不可見,僅僅用于組織數(shù)據(jù)。Partition 列有 partition 列的統(tǒng)計(jì),如該 partition 包含的數(shù)據(jù)范圍。當(dāng)用戶查詢時(shí),可以根據(jù) partition 的統(tǒng)計(jì)信息做 partition prune。

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

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

Delta

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

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

在查詢性能方面,開源的 Delta 幾乎沒有任何優(yōu)化。Iceberg 的 hidden partition 且不說,普通的 column 的統(tǒng)計(jì)信息也沒有。Databricks 對(duì)他們引以為傲的 Data Skipping 技術(shù)做了保留。不得不說這對(duì)于推廣 Delta 來說不是件好事。EMR 團(tuán)隊(duì)在這方面正在做一些工作,希望能彌補(bǔ)這方面能力的缺失。

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

deltaimage

總結(jié)

通過上面的分析能夠看到,三個(gè)引擎的初衷場(chǎng)景并不完全相同,Hudi 為了 incremental 的 upserts,Iceberg 定位于高性能的分析與可靠的數(shù)據(jù)管理,Delta 定位于流批一體的數(shù)據(jù)處理。這種場(chǎng)景的不同也造成了三者在設(shè)計(jì)上的差別。尤其是 Hudi,其設(shè)計(jì)與另外兩個(gè)相比差別更為明顯。隨著時(shí)間的發(fā)展,三者都在不斷補(bǔ)齊自己缺失的能力,可能在將來會(huì)彼此趨同,互相侵入對(duì)方的領(lǐng)地。當(dāng)然也有可能各自關(guān)注自己專長(zhǎng)的場(chǎng)景,筑起自己的優(yōu)勢(shì)壁壘,因此最終誰贏誰輸還是未知之?dāng)?shù)。
關(guān)注我的公眾號(hào),后臺(tái)回復(fù)【JAVAPDF】獲取200頁面試題!
5萬人關(guān)注的大數(shù)據(jù)成神之路,不來了解一下嗎?
5萬人關(guān)注的大數(shù)據(jù)成神之路,真的不來了解一下嗎?
5萬人關(guān)注的大數(shù)據(jù)成神之路,確定真的不來了解一下嗎?

歡迎您關(guān)注《大數(shù)據(jù)成神之路》
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容