一文徹底理解Apache Hudi的多版本清理服務

Apache Hudi提供了MVCC併發模型,保證寫入端和讀取端之間快照級別隔離。在本篇博客中我們將介紹如何配置來管理多個文件版本,此外還將討論用戶可使用的清理機制,以瞭解如何維護所需數量的舊文件版本,以使長時間運行的讀取端不會失敗。

1. 回收空間以控制存儲成本

Hudi 提供不同的表管理服務來管理數據湖上表的數據,其中一項服務稱爲Cleaner(清理服務)。 隨着用戶向表中寫入更多數據,對於每次更新,Hudi會生成一個新版本的數據文件用於保存更新後的記錄(COPY_ON_WRITE) 或將這些增量更新寫入日誌文件以避免重寫更新版本的數據文件 (MERGE_ON_READ)。 在這種情況下,根據更新頻率,文件版本數可能會無限增長,但如果不需要保留無限的歷史記錄,則必須有一個流程(服務)來回收舊版本的數據,這就是 Hudi 的清理服務。

2. 問題描述

在數據湖架構中,讀取端和寫入端同時訪問同一張表是非常常見的場景。由於 Hudi 清理服務會定期回收較舊的文件版本,因此可能會出現長時間運行的查詢訪問到被清理服務回收的文件版本的情況,因此需要使用正確的配置來確保查詢不會失敗。

3. 深入瞭解 Hudi清理服務

針對上述場景,我們先了解一下 Hudi 提供的不同清理策略以及需要配置的相應屬性,Hudi提供了異步或同步清理兩種方式。在詳細介紹之前我們先解釋一些基本概念:

  • Hudi 基礎文件(HoodieBaseFile):由壓縮後的最終數據組成的列式文件,基本文件的名稱遵循以下命名約定:<fileId>_<writeToken>_<instantTime>.parquet。在此文件的後續寫入中文件 ID 保持不變,並且提交時間會更新以顯示最新版本。這也意味着記錄的任何特定版本,給定其分區路徑,都可以使用文件 ID 和 instantTime進行唯一定位。
  • 文件切片(FileSlice):在 MERGE_ON_READ 表類型的情況下,文件切片由基本文件和由多個增量日誌文件組成。
  • Hudi 文件組(FileGroup):Hudi 中的任何文件組都由分區路徑和文件ID 唯一標識,該組中的文件作爲其名稱的一部分。文件組由特定分區路徑中的所有文件片組成。此外任何分區路徑都可以有多個文件組。

4. 清理服務

Hudi 清理服務目前支持以下清理策略:

  • KEEP_LATEST_COMMITS:這是默認策略。該清理策略可確保回溯前X次提交中發生的所有更改。假設每 30 分鐘將數據攝取到 Hudi 數據集,並且最長的運行查詢可能需要 5 小時才能完成,那麼用戶應該至少保留最後 10 次提交。通過這樣的配置,我們確保文件的最舊版本在磁盤上保留至少 5 小時,從而防止運行時間最長的查詢在任何時間點失敗,使用此策略也可以進行增量清理。
  • KEEP_LATEST_FILE_VERSIONS:此策略具有保持 N 個文件版本而不受時間限制的效果。當知道在任何給定時間想要保留多少個 MAX 版本的文件時,此策略很有用,爲了實現與以前相同的防止長時間運行的查詢失敗的行爲,應該根據數據模式進行計算,或者如果用戶只想維護文件的 1 個最新版本,此策略也很有用。

5. 例子

假設用戶每 30 分鐘將數據攝取到 COPY_ON_WRITE 類型的 Hudi 數據集,如下所示:

圖1:每30分鐘將傳入的記錄提取到hudi數據集中

該圖顯示了 DFS 上的一個特定分區,其中提交和相應的文件版本是彩色編碼的。在該分區中創建了 4 個不同的文件組,如 fileId1、fileId2、fileId3 和 fileId4 所示。 fileId2 對應的文件組包含所有 5 次提交的記錄,而 fileId4 對應的組僅包含最近 2 次提交的記錄。

假設使用以下配置進行清理:

hoodie.cleaner.policy=KEEP_LATEST_COMMITS
hoodie.cleaner.commits.retained=2

Cleaner 通過處理以下事項來選擇要清理的文件版本:

  • 不應清理文件的最新版本。
  • 確定最後 2 次(已配置)+ 1 次提交的提交時間。在圖 1 中,commit 10:30commit 10:00 對應於時間線中最新的 2 個提交。包含一個額外的提交,因爲保留提交的時間窗口本質上等於最長的查詢運行時間。因此如果最長的查詢需要 1 小時才能完成,並且每 30 分鐘發生一次攝取,則您需要保留自 2*30 = 60(1 小時)以來的最後 2 次提交。此時最長的查詢仍然可以使用以相反順序在第 3 次提交中寫入的文件。這意味着如果一個查詢在 commit 9:30 之後開始執行,當在 commit 10:30 之後觸發清理操作時,它仍然會運行,如圖 2 所示。
  • 現在對於任何文件組,只有那些沒有保存點(另一個 Hudi 表服務)且提交時間小於第 3 次提交(下圖中的“提交 9:30”)的文件切片被清理。

圖2:保留最近3次提交對應的文件

假設使用以下配置進行清理:

hoodie.cleaner.policy=KEEP_LATEST_FILE_VERSIONS
hoodie.cleaner.fileversions.retained=1

清理服務執行以下操作:

  • 對於任何文件組,文件切片的最新版本(包括任何待壓縮的)被保留,其餘的清理掉。 如圖 3 所示,如果在 commit 10:30 之後立即觸發清理操作,清理服務將簡單地保留每個文件組中的最新版本並刪除其餘的。

圖3:保留每個文件組中的最新文件版本

6. 配置

可以在 此處 中找到有關所有可能配置的詳細信息以及默認值。

7. 運行命令

Hudi 的清理表服務可以作爲單獨的進程運行,可以與數據攝取一起運行。正如前面提到的,它會清除了任何陳舊文件。如果您想將它與攝取數據一起運行,可以使用配置同步或異步運行。或者可以使用以下命令獨立運行清理服務:

[hoodie]$ spark-submit --class org.apache.hudi.utilities.HoodieCleaner \
  --props s3:///temp/hudi-ingestion-config/config.properties \
  --target-base-path s3:///temp/hudi \
  --spark-master yarn-cluster

如果您希望與寫入異步運行清理服務,可以配置如下內容:

hoodie.clean.automatic=true
hoodie.clean.async=true

此外還可以使用 Hudi CLI 來管理 Hudi 數據集。CLI 爲清理服務提供了以下命令:

  • cleans show
  • clean showpartitions
  • clean run

可以在 org.apache.hudi.cli.commands.CleansCommand 中找到這些命令的更多詳細信息和相關代碼。

8. 未來計劃

目前正在進行根據已流逝的時間間隔引入新的清理策略,即無論攝取發生的頻率如何,都可以保留想要的文件版本,可以在 此處 跟蹤進度。

我們希望這篇博客能讓您瞭解如何配置 Hudi 清理服務和支持的清理策略。請訪問博客部分 以更深入地瞭解各種 Hudi 概念。

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