Hudi 1.0 新功能預(yù)覽

一、Apache Hudi 簡(jiǎn)介

Hudi 是一個(gè)高效的事務(wù)型數(shù)據(jù)湖倉(cāng)平臺(tái),其核心特色是一個(gè)開(kāi)放性的表格式定義和一套全面的事務(wù)數(shù)據(jù)庫(kù)核心層。這一核心層不僅支持索引功能,還能高效地處理并發(fā)事務(wù),并具備強(qiáng)大的變更數(shù)據(jù)捕獲能力。在數(shù)據(jù)管道中,Hudi 能夠從上游數(shù)據(jù)源如 Kafka 接收數(shù)據(jù),并利用 Spark 和 Flink 等執(zhí)行引擎進(jìn)行數(shù)據(jù)導(dǎo)入與處理。平臺(tái)還提供自動(dòng)文件大小調(diào)整、增量處理和變更捕獲等功能,以優(yōu)化數(shù)據(jù)的清理與轉(zhuǎn)換。此外,Hudi 具備豐富的表服務(wù)能力,如數(shù)據(jù)清理和聚類,確保數(shù)據(jù)管理的高效性。Hudi 已與眾多數(shù)據(jù)生態(tài)系統(tǒng)組件廣泛集成,包括目錄同步和多種查詢引擎,以實(shí)現(xiàn)數(shù)據(jù)處理的多樣化和靈活性。

上圖是 Hudi 的架構(gòu)分層圖,展示了其作為數(shù)據(jù)湖倉(cāng)平臺(tái)的三個(gè)核心層級(jí)。最底層用綠色表示的是開(kāi)放的存儲(chǔ)層,負(fù)責(zé)底層數(shù)據(jù)的存儲(chǔ),使用諸如 Parquet、Avro 和 ORC 等開(kāi)源文件格式。其上一層是事務(wù)性數(shù)據(jù)庫(kù)核心層,該層定義了數(shù)據(jù)表格式、數(shù)據(jù)表服務(wù)、索引機(jī)制以及并發(fā)控制,確保了數(shù)據(jù)的一致性和高效處理。最頂層是開(kāi)放平臺(tái)服務(wù)層,提供了一套開(kāi)發(fā)的 API,支持與各類集成生態(tài)技術(shù)的讀寫操作,并實(shí)現(xiàn)了平臺(tái)的功能性,包括元數(shù)據(jù)服務(wù)、數(shù)據(jù)入湖工具和與不同查詢引擎的集成。這些層級(jí)共同構(gòu)成了 Hudi 的平臺(tái)架構(gòu),使得用戶和開(kāi)發(fā)人員能夠直接與平臺(tái)服務(wù)及工具交互,而機(jī)器則通過(guò)底層的讀寫支持與數(shù)據(jù)庫(kù)核心層交互。在 Hudi 1.0 版本中,這些架構(gòu)層級(jí)經(jīng)過(guò)了新的性能和功能優(yōu)化,以滿足現(xiàn)代數(shù)據(jù)管理的需求。
二、Hudi 1.0 的重新思考

Hudi 1.0 的構(gòu)想源于對(duì) Hudi 成長(zhǎng)歷程的回顧。Hudi 最初旨在解決大規(guī)模數(shù)據(jù)攝取、增量數(shù)據(jù)處理和快速創(chuàng)建的問(wèn)題,并需要與 Presto、Spark、Flink、Trino 等查詢引擎集成。雖然這些引擎在列式數(shù)據(jù)查詢方面表現(xiàn)出色,但它們的整合過(guò)程卻充滿挑戰(zhàn)。
作為湖倉(cāng)領(lǐng)域的先鋒,Hudi 曾被稱為事務(wù)性數(shù)據(jù)湖。在生態(tài)系統(tǒng)的早期階段,Hudi 做出了一些保守的設(shè)計(jì)選擇,例如為不同的查詢引擎開(kāi)發(fā)了各自的連接器。在過(guò)去的五年中,Hudi 社區(qū)蓬勃發(fā)展,同時(shí)也暴露出更多元化的需求,特別是在事務(wù)性操作、快速更新和刪除功能方面。因此,Hudi 團(tuán)隊(duì)認(rèn)識(shí)到有必要對(duì)現(xiàn)有設(shè)計(jì)進(jìn)行深層次的重新思考和優(yōu)化,以適應(yīng)不斷變化的數(shù)據(jù)處理需求。

Hudi 1.0 的五大發(fā)展方向體現(xiàn)了對(duì)當(dāng)前數(shù)據(jù)湖架構(gòu)的深度思考和對(duì)未來(lái)規(guī)劃的遠(yuǎn)見(jiàn):
- 深度查詢引擎集成:Hudi 將探索更深層次的查詢引擎集成,減少對(duì)多個(gè)專屬連接器的依賴。通過(guò)深入集成 Hudi 的多模索引(metadata table)功能,并結(jié)合如 Velox 等組件,以提升查詢性能。
- 泛化的關(guān)系型數(shù)據(jù)模型:隨著越來(lái)越多的引擎支持更全面的 SQL 語(yǔ)法,Hudi 將擴(kuò)展其數(shù)據(jù)模型,以更好地適應(yīng)關(guān)系型數(shù)據(jù)處理的需求,充分利用現(xiàn)代數(shù)據(jù)生態(tài)系統(tǒng)的優(yōu)勢(shì)。
- 有服務(wù)器和無(wú)服務(wù)器的架構(gòu)配置:Hudi 將發(fā)展混合架構(gòu),結(jié)合有服務(wù)器和無(wú)服務(wù)器配置,以適應(yīng)不同的數(shù)據(jù)處理需求。元數(shù)據(jù)服務(wù)將得到加強(qiáng),以支持更高效的并發(fā)控制和商用元數(shù)據(jù)服務(wù)的集成。
- 非結(jié)構(gòu)化數(shù)據(jù)支持:Hudi 將擴(kuò)展對(duì)非結(jié)構(gòu)化數(shù)據(jù)(如圖像、視頻)的支持,以避免數(shù)據(jù)湖的碎片化,并實(shí)現(xiàn)非結(jié)構(gòu)化數(shù)據(jù)的索引更新和變更捕獲功能,以適應(yīng) AI 等新興技術(shù)的需求。
- 數(shù)據(jù)庫(kù)表的自我管理能力提升:Hudi 將繼續(xù)完善其數(shù)據(jù)湖表管理服務(wù),包括數(shù)據(jù)入湖、表服務(wù)計(jì)劃執(zhí)行和運(yùn)維工具。未來(lái)將增加更多功能,如反向流數(shù)據(jù)導(dǎo)入、快照管理、檢驗(yàn)分析報(bào)告工具、跨區(qū)域備份和記錄級(jí)別的 TTL 管理,以實(shí)現(xiàn)更全面的數(shù)據(jù)表管理。

在對(duì)比數(shù)據(jù)庫(kù)的經(jīng)典設(shè)計(jì)架構(gòu)與 Hudi 的架構(gòu)時(shí),我們可以看到 Hudi 在數(shù)據(jù)湖倉(cāng)領(lǐng)域?qū)崿F(xiàn)了一個(gè)類似數(shù)據(jù)庫(kù)的功能層次。最頂層的客戶端模塊是用戶與系統(tǒng)交互的接口,負(fù)責(zé)處理 SQL 層的請(qǐng)求。在此之下,Hudi 集成了不同查詢引擎的查詢解析和優(yōu)化功能,目前主要依賴各引擎自身的優(yōu)化,但未來(lái)可能引入 Hudi 內(nèi)部的優(yōu)化機(jī)制。
藍(lán)色的模塊代表與外部系統(tǒng)的集成,而中間的方塊則展示了 Hudi 實(shí)現(xiàn)的事務(wù)性管理機(jī)制,這與傳統(tǒng)數(shù)據(jù)庫(kù)中的鎖管理、日志管理等模塊相對(duì)應(yīng)。已經(jīng)實(shí)現(xiàn)的組件用綠色方塊表示,而像緩存管理這樣的未來(lái)愿景則用其他顏色表示,這表明了 Hudi 1.0 版本的發(fā)展方向。
三、Hudi 1.0-beta 的重點(diǎn)新功能

接下來(lái),將介紹 Hudi 1.0 的一些關(guān)鍵功能。Hudi 1.0 版本的設(shè)計(jì)理念可以在其RFC(Request for Comments)文檔中找到,該文檔詳細(xì)介紹了版本的主要設(shè)計(jì)方向和預(yù)期特性。

接下來(lái)將重點(diǎn)討論幾個(gè)關(guān)鍵功能,首先是 Hudi 的 LSM tree 時(shí)間線。Hudi 的時(shí)間線本質(zhì)上是一個(gè)不可變的事務(wù)日志,記錄了表上所有已完成交易的詳細(xì)信息。這個(gè)事務(wù)日志通常會(huì)隨著每次提交而線性增長(zhǎng)。Hudi 0.x 版本維護(hù)了兩個(gè)時(shí)間線:活躍時(shí)間線和歸檔時(shí)間線?;钴S時(shí)間線用于快速檢索最新信息,而歸檔時(shí)間線則用于滿足特定場(chǎng)景下的歷史數(shù)據(jù)查詢需求。由于歸檔數(shù)據(jù)采用了不同的存儲(chǔ)機(jī)制,訪問(wèn)這些數(shù)據(jù)的成本相對(duì)較高。

為了優(yōu)化 Hudi 時(shí)間線的存儲(chǔ)效率,我們考慮采用 LSM tree 這種經(jīng)過(guò)驗(yàn)證的高效數(shù)據(jù)結(jié)構(gòu),它特別適合處理大規(guī)模寫入操作。在 Hudi 1.0 中,我們重新實(shí)現(xiàn)了寫入時(shí)間線的機(jī)制,現(xiàn)在每次寫入都會(huì)記錄其起始和結(jié)束時(shí)間。此外,我們將現(xiàn)有的線性存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)換成了 LSM tree 結(jié)構(gòu),這允許進(jìn)行更高效的壓縮操作。
LSM tree 的優(yōu)勢(shì)在于其樹形分層結(jié)構(gòu),能夠在頂層(如內(nèi)存或緩存)快速檢索信息,同時(shí)在更長(zhǎng)的時(shí)間線上,可以通過(guò)壓縮多個(gè)事務(wù)到更大的 parquet 文件中,來(lái)提高讀取效率和存儲(chǔ)效率。這種結(jié)構(gòu)不僅優(yōu)化了數(shù)據(jù)的快速訪問(wèn),還提升了整體存儲(chǔ)的緊湊性和性能。

接下來(lái)對(duì) LSM Tree 時(shí)間線進(jìn)行了一系列測(cè)試,其中包括模擬了 100 萬(wàn)次提交的交易日志。在無(wú)需加載所有元數(shù)據(jù)的情況下,僅訪問(wèn)開(kāi)始時(shí)間和結(jié)束時(shí)間以及事務(wù)中涉及的文件,我們實(shí)現(xiàn)了在 367ms 內(nèi)加載整個(gè)時(shí)間線。這一性能提升得益于將時(shí)間線數(shù)據(jù)存儲(chǔ)為 parquet 文件,這不僅減少了讀取所需的元數(shù)據(jù)量,還提供了更高的讀取靈活性,從而顯著提高了加載效率。

接下來(lái)探討另一個(gè)關(guān)鍵功能:函數(shù)索引。Hudi 的當(dāng)前版本已經(jīng)集成了一個(gè)多模式索引子系統(tǒng),支持文件索引、列統(tǒng)計(jì)和布隆過(guò)濾器等功能,且這些索引可以異步構(gòu)建。在 Hudi 1.0 中,我們希望進(jìn)一步增強(qiáng)多模式索引的通用性。受到數(shù)據(jù)庫(kù)索引機(jī)制的啟發(fā),我們考慮了基于 R 樹的空間索引和基于 Lucene 的搜索索引等高級(jí)功能。例如,PostgreSQL 能夠在表達(dá)式上創(chuàng)建索引,這啟發(fā)了我們實(shí)現(xiàn)函數(shù)索引的思路。函數(shù)索引的引入將使 Hudi 的索引功能更加靈活和強(qiáng)大,從而提高查詢效率和處理復(fù)雜查詢的能力。

函數(shù)索引的一個(gè)典型用例是在處理包含組織 ID 和時(shí)間戳的事件流數(shù)據(jù)時(shí)。通常,我們希望根據(jù)組織 ID 進(jìn)行分區(qū),然后進(jìn)一步根據(jù)時(shí)間戳細(xì)分。例如,如果有1,000 個(gè)組織的一整年數(shù)據(jù),我們可能會(huì)創(chuàng)建 365,000 個(gè)分區(qū)。然而,這種做法可能會(huì)導(dǎo)致數(shù)據(jù)傾斜和大量小文件的問(wèn)題,這既影響了存儲(chǔ)效率,也降低了查詢性能。
為了解決這個(gè)問(wèn)題,Hudi 1.0 引入了函數(shù)索引。我們僅根據(jù)組織 ID 進(jìn)行物理分區(qū),然后為時(shí)間戳定義一個(gè)函數(shù),比如將 Unix 時(shí)間戳轉(zhuǎn)換為小時(shí),并記錄每個(gè)小時(shí)的最大值和最小值。這樣就可以在索引中實(shí)現(xiàn)高效的 data skipping,即跳過(guò)不需要掃描的數(shù)據(jù),同時(shí)保持文件存儲(chǔ)的高效率,無(wú)需進(jìn)行更細(xì)粒度的物理分區(qū)。這種方法既保留了存儲(chǔ)效率,又提供了更靈活的分區(qū)結(jié)構(gòu),優(yōu)化了查詢性能和數(shù)據(jù)管理。

函數(shù)索引的使用可以通過(guò)一個(gè)簡(jiǎn)單的示例來(lái)解釋。在左側(cè)的 SQL 示例中,使用 city 來(lái)分區(qū),同時(shí)還有一個(gè)時(shí)間戳字段。我們不需要針對(duì)時(shí)間戳進(jìn)一步分區(qū),而是可以使用 create index 的語(yǔ)法來(lái)生成一個(gè)新的索引,該索引將時(shí)間戳轉(zhuǎn)換為小時(shí)。一旦生成了這個(gè)索引,隨后的 SELECT 語(yǔ)句就可以利用時(shí)間戳進(jìn)行高效的數(shù)據(jù)跳過(guò)。
在右側(cè)的兩個(gè) Spark DAG(有向無(wú)環(huán)圖)演示中,展示了在有函數(shù)索引和沒(méi)有函數(shù)索引的情況下,數(shù)據(jù)跳過(guò)是如何實(shí)現(xiàn)的。使用函數(shù)索引,Spark 查詢可以更有效地跳過(guò)不相關(guān)數(shù)據(jù),從而提高查詢性能和減少資源消耗。這種索引策略不僅簡(jiǎn)化了數(shù)據(jù)分區(qū),還提升了整體的數(shù)據(jù)處理效率。

另一個(gè)重要的功能改進(jìn)是 Hudi 新開(kāi)發(fā)的文件組讀取器和寫入器。Hudi 自創(chuàng)建之初就設(shè)計(jì)了一個(gè)基于主鍵的概念。在 MOR(Merge-On-Read)表類型中,我們實(shí)現(xiàn)了一個(gè)合并操作,從第一天起就支持快照查詢,即實(shí)時(shí)地將日志數(shù)據(jù)合并到基礎(chǔ)文件中。這一機(jī)制確保了即使在數(shù)據(jù)不斷寫入和更新時(shí),也能高效地執(zhí)行查詢操作,提供了對(duì)歷史和最新數(shù)據(jù)的統(tǒng)一視圖。

對(duì)于 Hudi 中的合并操作,我們發(fā)現(xiàn)了潛在的優(yōu)化空間。具體來(lái)說(shuō),我們可以在記錄日志的同時(shí),記錄下日志所需更新的基礎(chǔ)文件的位置信息。這樣,在進(jìn)行合并操作時(shí),能夠直接定位到文件的具體位置,從而高效地執(zhí)行合并。
此外,Hudi 1.0 增加了對(duì)部分更新(partial update)的優(yōu)先支持。傳統(tǒng)的日志文件默認(rèn)記錄整條更新語(yǔ)句,但在許多情況下,只需記錄更新的字段。通過(guò)僅記錄更新的字段及其值和位置,能夠極大優(yōu)化合并過(guò)程。
設(shè)計(jì)文件組讀取器和寫入器的另一個(gè)好處是,它使得與各種查詢引擎的集成變得更加簡(jiǎn)便。這種設(shè)計(jì)統(tǒng)一了接口,使得擴(kuò)展對(duì)不同引擎的支持變得更加方便,從而提升了 Hudi 的整體靈活性和可擴(kuò)展性。

針對(duì)基于位置的合并操作,我們進(jìn)行了一系列基準(zhǔn)測(cè)試。這些測(cè)試涉及了兩個(gè)不同規(guī)模的合并表,一個(gè)包含 500GB、7.5 億條記錄,另一個(gè)包含 1TB、15 億條記錄。每條記錄大約 1KB 大小,表包含 1000 個(gè)分區(qū),每個(gè)文件大約 256MB。
在測(cè)試中,我們首先批量加載數(shù)據(jù),然后執(zhí)行刪除和更新操作,更新表中 50% 的記錄。通過(guò)使用文件組讀取器并利用位置信息進(jìn)行合并操作,我們觀察到了 12% 到 20% 的性能提升。這一提升隨著數(shù)據(jù)量的增加而變得更加顯著。對(duì)于具體的性能數(shù)據(jù)和詳細(xì)分析,可以參考 Hudi 的 PR 10167。

在部分更新(partial update)的測(cè)試中,我們觀察到了更為顯著的性能提升。上圖中展示了更新操作的結(jié)果對(duì)比。當(dāng)使用全量更新,即整條記錄的所有字段與僅更新部分字段時(shí),更新的延遲降低了 1.4 倍。同時(shí),寫入的文件大小減少了 70 倍,這是因?yàn)槲覀児?jié)省了大量未更新的數(shù)據(jù)。由于寫入更為高效,節(jié)省了空間,合并操作也變得更為高效,我們觀察到了 5.7 倍的性能提升。這些優(yōu)化不僅提高了更新操作的效率,還顯著減少了存儲(chǔ)空間的占用。

最后一個(gè)重點(diǎn)功能是非阻塞并發(fā)控制。這個(gè)設(shè)計(jì)基于一個(gè)常見(jiàn)場(chǎng)景:一個(gè)每分鐘寫入的進(jìn)程和每小時(shí)執(zhí)行一次的 GDPR 刪除作業(yè)。如果采用樂(lè)觀鎖機(jī)制,刪除作業(yè)可能會(huì)頻繁遇到?jīng)_突,因?yàn)閯h除操作是隨機(jī)的,這會(huì)導(dǎo)致刪除作業(yè)在大多數(shù)情況下都需要重試,從而浪費(fèi)資源。
Hudi 從一開(kāi)始就采用了 MVCC(多版本并發(fā)控制)機(jī)制。在寫入側(cè),允許不加阻塞地寫入,而在使用 MOR 模式時(shí),在合并側(cè)執(zhí)行異步合并操作。此外,我們可以利用合并的機(jī)會(huì)進(jìn)行類聚操作,以優(yōu)化存儲(chǔ)。這種設(shè)計(jì)確保了在處理并發(fā)寫入和刪除操作時(shí),系統(tǒng)的效率和資源利用率得到提高。

為了解決多個(gè)寫入器并發(fā)控制的問(wèn)題,Hudi 支持樂(lè)觀鎖的使用,也引入了早期沖突檢測(cè)機(jī)制。此外,Hudi 探索了更通用的非阻塞多版本并發(fā)控制機(jī)制。在 Hudi 1.0 中,我們實(shí)現(xiàn)了一個(gè)基于 MOR 寫入過(guò)程的非阻塞并發(fā)控制。
當(dāng) MOR 寫入操作在不同寫入器上生成不同的日志文件時(shí),Hudi 最初不會(huì)阻塞寫入過(guò)程。通過(guò)使用全局單調(diào)遞增的時(shí)間戳來(lái)記錄每個(gè)寫入的開(kāi)始和結(jié)束時(shí)間,我們可以在合并或快照讀取階段解決潛在的沖突。這種方法允許在寫入時(shí)保持非阻塞狀態(tài),從而提高了寫入效率,同時(shí)確保了數(shù)據(jù)的最終一致性。

今天的重點(diǎn)內(nèi)容已經(jīng)介紹完畢。關(guān)于 Hudi 1.0,這里再提供一些額外信息。Hudi 1.0 的技術(shù)文檔已經(jīng)發(fā)表,可以在相應(yīng)的鏈接中查閱。此外,相關(guān)的RFC 文檔和設(shè)計(jì)文檔也已公開(kāi),供社區(qū)參考。Hudi 1.0 beta1 的 jar 包也已經(jīng)發(fā)布。這些資源將為希望深入了解 Hudi 1.0 的用戶和開(kāi)發(fā)者提供幫助。


最后,展示一下 Hudi 社區(qū)的活躍情況。社區(qū)非常歡迎新成員的加入,這里提供了豐富的文檔鏈接和資源,以便大家更好地了解和參與 Hudi 項(xiàng)目。此外,歡迎關(guān)注 Hudi 的公眾號(hào)來(lái)獲取最新信息,也歡迎加入我們的社區(qū),共同推動(dòng) Hudi 的發(fā)展。
四、相關(guān)鏈接
1.0技術(shù)spec:https://hudi.apache.org/tech-specs-1 point0。
Docs : https://hudi.apache.org。
Blogs : https://hudi.apache.org/blog。
slack:https://join.slack.com/t/apache-hudi/shared_invite/zt-2ggm1fub8-_yt4Reu9djwqqVRFC7X49g。
Twitter : https://twitter.com/apachehudi。
Github: https://github.com/apache/hudi/。
Mailing list(s) : dev-subscribe@hudi.apache.org (send an empty email to subscribe)。



























