地表最強!數據湖三劍客

Introduction

在構建數據湖時,也許沒有比數據格式存儲更具有意義的決定。其結果將對其性能、可用性和兼容性產生直接影響。

通過簡單地改變數據的存儲格式,我們就可以解鎖新的功能,提高整個系統的性能,這很有啓發意義。

Apache Hudi、Apache Iceberg 和 Delta Lake 是目前爲數據湖設計的最佳格式。這三種格式都解決了數據湖最迫切的一些問題。

  1. 原子事務 -- 保證對數據湖的更新或追加操作不會中途失敗,產生髒數據。

  2. 一致的更新 -- 防止在寫入過程中讀取失敗或返回不完整的結果。同時處理潛在的併發寫入衝突。

  3. 數據和元數據的可擴展性 -- 當表增長到數千個分區和數十億文件的大小時,避免對象存儲 API 和相關元數據的瓶頸。

讓我們仔細分析下每種格式在更新性能、併發性和與其他工具的兼容性方面的做法。最後,我們將就某種格式對你的數據湖建設提出最有意義的建議

Platform Compatibility

HudiHudi 最初是由 Uber 開源的,它被設計成支持通過列式數據格式進行增量更新。它支持從多個來源攝取數據,主要是 Apache Spark 和 Apache Flink。它還提供了一個基於 Spark 的實用程序(DeltaStreamer)來讀取外部資源,如 Apache Kafka。

支持從 Apache Hive、Apache Impala 和 PrestoDB 讀取數據。還有一個專門的工具(HiveSyncTool)可以將 Hudi 表模式同步到 Hive Metastore 中。ps:Hudi 社區也支持 DLA

iceberg

Iceberg 最初由 Netflix 發佈,旨在解決在 S3 上存儲大型 Hive-Partitioned 數據集時出現的性能、可擴展性和可管理性挑戰。

iceberg 支持 Apache Spark 的讀和寫,包括 Spark 的結構化流。Trino (PrestoSQL) 也支持讀取,但對刪除的支持有限。同時支持 Apache Flink 的讀和寫。最後,Iceberg 爲 Apache Hive 提供了讀支持。

Delta Lake

Delta Lake 是由 Databricks(Apache Spark 的創建者)作爲一個開源項目進行維護,並不奇怪,它與 Spark 在讀寫方面都進行了深度集成。

使用 Hive 的 SymlinkTextInputFormat 爲 Presto、AWS Athena、AWS Redshift Spectrum 和 Snowflake 提供讀取支持。儘管這需要爲每個 Delta 表分區導出一個 symlink.txt 文件,而且正如你所說,對於較大的表來說,維護成本變得很高。

Update Performance & Throughput

對大型、不可變對象的行級更新的支持可以通過幾種方式來實現,每種方式都有其獨特的關於性能和吞吐量的權衡。

讓我們看看每種數據格式對 UPSERT 操作採用的策略。我們還將談到與讀取性能相關的額外優化。

Hudi

hudi 表在處理 UPSERTS 時提供的性能權衡是靈活的(明確的)。兩種不同類型的 Hudi 表之間的權衡是不同的。

Copy on Write Table - 更新完全寫在列式拼接文件中,創建新的對象。這增加了寫的成本,但將讀放大降低到零,使其成爲讀重工作負載的理想選擇。Merge on read Table - 更新立即寫入基於行的日誌文件中,並定期合併到列式 parquet 中。有趣的是,查詢可以包含最新的日誌文件數據(快照視圖),也可以不包含(讀優化視圖),爲用戶在數據延遲和查詢效率之間提供不同的選擇性

Hudi 通過利用關鍵索引進一步優化壓縮,有效地跟蹤哪些文件包含陳舊的記錄。

iceberg

隨着去年夏天 Spark 3.0 的發佈,Iceberg 通過 MERGE INTO 查詢支持 upserts。它們使用直接的複製 - 寫的方式工作,其中包含需要更新記錄的文件會立即被重寫。

Iceberg 的優勢在於包含大量分區的表的讀取性能。通過維護 manifest 文件,將對象映射到分區,並保持列級統計,Iceberg 避免了昂貴的對象存儲目錄列表或需要從 Hive 獲取分區數據。

此外,Iceberg 的清單允許一個文件同時分配到多個分區。這使得 Iceberg 表能高效地進行分區修剪,並改善了高選擇性查詢的延遲。

Delta Lake

在 MERGE 操作過程中,Delta 使用元數據信息的數據跳轉,將文件分類爲需要插入、更新或刪除的數據。然後,它執行這些操作,並將它們作爲 "提交" 記錄在一個名爲 Delta Log 的 JSON 日誌文件中。這些日誌文件每 10 次提交就會重寫一次,作爲 Parquet 的 "檢查點" 文件,保存整個表的狀態,以防止昂貴的日誌文件遍歷。

爲了保持性能,Delta 表需要定期進行壓縮處理,將許多小的 Parquet 文件合併成較少的大文件(最佳情況下約 1GB,但至少 128MB 大小)。Databricks 的專有版本 Delta Engine 支持自動壓實,該過程會自動觸發,並支持其他幕後寫優化。

Delta Engine 通過使用 Bloom Filters 提供關鍵索引、Z-Ordering 以在讀取時更好地修剪文件、本地緩存等,進一步提升了其開源版本的性能。

Concurrency Guarantees

允許數據表的 in-place 更新意味着要處理併發性問題。

如果有人在更新表的同時讀取表,會發生什麼?而當多個 writer 同時進行衝突的修改時,又會怎樣?

通常數據庫通過多版本併發控制(MVCC)來解決這個問題,這種方法利用一個邏輯事務日誌,所有的更改都會被追加。

另一種稱爲優化併發控制(OCC)的方法允許同時發生多個寫入,只在最後提交前檢查衝突。如果檢測到衝突,其中一個事務會被重試,直到成功。

Hudi

True to form,Hudi 提供 MVCC 和 OCC 併發控制。

Hudi 的 MVCC 意味着所有的寫入必須在其中心日誌中完全有序。爲了提供這種保證,Hudi 將寫併發量限制爲 1,這意味着在一個給定的時間點上,只能有一個 writer 對一個表進行寫。

爲了防止這種限制,Hudi 現在提供了 OCC。這個功能需要 Apache Zookeeper 或者 Hive Metastore 來鎖定單個文件並提供隔離。

Iceberg

iceberg 通過在更新過程中對元數據文件進行原子交換操作來支持優化併發(OCC)。

其工作方式是每次寫入都會創建一個新的表 "快照"。然後,寫入者會嘗試對一個持有當前快照 ID 的特殊值進行比較和交換(CAS)操作。如果在提交過程中沒有其他寫入者替換快照,則操作成功。如果在此期間有另一個寫入者進行提交,另一個寫入者將不得不重試,直到成功。

在分佈式文件系統上,如 HDFS,這可以在本地完成。對於 S3,需要一個額外的組件來存儲指針(目前只支持 Hive Metastore)。

Delta Lake

據 Delta 文檔解釋,它使用 Optimistic Control 來處理併發性,因爲大多數數據湖操作都會將數據追加到一個時間排序的分區,不會發生衝突。

在兩個進程向 Delta Log 文件添加提交的情況下,Delta 會 "默默地、無縫地" 檢查文件變化是否重疊,如果可能的話,會讓兩個進程都成功。

不過這意味着,底層對象存儲需要提供一種方式,當多個寫入者開始覆蓋對方的日誌條目時,要麼提供 CAS 操作,要麼提供一種寫入失敗的方式。

與 Iceberg 類似,這個功能在 HDFS 上是可以開箱即用的,但 S3 不支持。因此,在 AWS 上的 Delta 不支持從多個 Spark 集羣進行寫入,且沒有真正的事務性保證。

注意:專有的 Delta Engine 版本支持使用 Databricks 自己管理的外部同步服務器在 S3 上進行多集羣寫入。

So which one is right for you?

如果你看到這裏,我們已經瞭解了 Apache Hudi、Delta Lake 和 Apache Iceberg 之間的一些重要的相似之處和不同之處。

現在是時候決定哪種格式對你的用例最有意義了! 我的建議是取決那種情況最適用

Go with Iceberg if…

你的主要痛點不是對現有記錄的更改,而是在對象存儲上管理巨大的表(超過 10k 個分區)的元數據負擔。採用 Iceberg 將緩解與 S3 對象列表或 Hive Metastore 分區枚舉相關的性能問題。

相反,對刪除和變更的支持還是初步的,而且涉及到數據保留的操作開銷。

Go with Hudi if…

你使用各種查詢引擎,並且需要靈活管理變更的數據集。請注意,支持工具和整體的開發者體驗可能較差。儘管有可能,但爲實際的大規模生產工作負載安裝和調試 Hudi 也需要一定的操作開銷。

如果你正在使用 AWS 管理服務,如 Athena,Glue 或 EMR - Hudi 已經預裝和配置,並由 AWS 支持。

Go with Delta Lake if…

你主要是一個 Spark 商店,並且期望相對較低的寫入吞吐量。如果你也已經是 Databricks 的客戶,Delta Engine 爲讀寫性能和併發量都帶來了顯著的改善,對他們的生態系統進行雙重開發是很有意義的。

對於其他 Apache Spark 發行版來說,要明白 Delta Lake 雖然是開源的,但很可能會一直落後於 Delta Engine,以起到產品差異化的作用。

Integration With lakeFS

如果你想知道 "我可以用 lakeFS 和這些數據格式一起使用嗎?"...... 答案是肯定的。

lakeFS 可以與 Delta、Iceberg 或 Hudi 中的任何一種共生,提供跨任何數量的表進行分支、合併、回滾等操作的能力。

由於這些格式都是在表級操作,所以對跨多個表的操作沒有提供保證。通過 lakeFS,可以在一個孤立的分支上修改多個表,然後將這些修改原子地合併到一個主分支上,實現跨表的一致性

Further Reading

This article was contributed to by Paul Singman, Developer Advocate at lakeFS.

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/8wO0HcLSp6fHJQketjhq4g