在花了大約 4 年時間致力於 Apache Hudi(其中包括 3 年Committer身份)之後,我決定開始這個博客系列,旨在以有組織且適合初學者的方式展示 Hudi 的設計和用法。 我的目標是確保對分佈式數據系統有一定了解的人能夠輕鬆地理解該系列。 該系列將包含 10 篇文章,每篇文章都會深入探討 Hudi 的一個關鍵方面。 (爲什麼是 10?純粹是對 0 和 1 的有趣致敬,與系列標題相呼應:))最終目標是幫助讀者從廣度和深度上理解 Hudi,使他們能夠自信地利用這個開源項目併爲其做出貢獻。 在撰寫本文時,Hudi 0.14.0 正處於候選版本階段。 因此,整個系列以及配套代碼和示例都將基於此版本。
概述
Hudi 是一個事務性數據湖平臺,它將數據庫和數據倉庫功能引入數據湖。 下圖摘自 Hudi 社區舉辦的網絡研討會,清楚地說明了該平臺的主要功能
Hudi 的核心定義了一種表格式,用於組織存儲系統內的數據和元數據文件,從而實現 ACID 事務、高效索引和增量處理等功能。 本文的其餘部分將探討格式詳細信息,主要展示存儲上的 Hudi 表的結構並解釋不同文件的角色。
存儲格式
下圖描述了 Hudi 表在存儲中的基本路徑下的典型數據佈局。
有兩種主要類型的文件:位於 .hoodie/
目錄中的元數據文件,以及存儲在分區路徑中(如果表已分區)的數據文件,或者直接在基本路徑(如果未分區)下的數據文件。
元數據
<base path>/.hoodie/hoodie.properties
文件包含基本的表配置,例如表名稱和版本,表的寫入端和讀取端都將遵守和使用這些配置。
除了 hoodie.properties 之外,還有將事務操作記錄到表中的元文件,形成 Hudi 表的時間軸。
# an example of deltacommit actions on Timeline
20230827233828740.deltacommit.requested
20230827233828740.deltacommit.inflight
20230827233828740.deltacommit
這些元文件遵循以下命名模式:
<action timestamp>.<action type>[.<action state>]
"action timestamp"
- 標記第一次計劃運行操作的時間。
- 唯一標識時間軸上的操作。
- 在時間軸上的不同操作之間單調遞增。
"action type"顯示該動作做出了什麼樣的改變。 有一些寫入操作類型,例如 commit 和 deltacommit,它們指示表上發生的新寫入操作(插入、更新或刪除)。 此外,還有表服務操作,例如壓縮和清理,以及恢復操作,例如保存點和恢復。 我們將在以後的帖子中更詳細地討論不同的操作類型。
"action state"可以是“已請求”、“進行中”或“已完成”(沒有後綴)。 顧名思義,“已請求”表示正在計劃運行,“正在執行”表示正在進行中,“已完成”表示操作已完成。
這些操作的元文件採用 JSON 或 AVRO 格式,包含有關應應用於表或已應用的更改的信息。 保留這些事務日誌可以重新創建表的狀態,實現快照隔離,並通過併發控制機制協調寫入器衝突。
.hoodie/
下還存儲有其他元數據文件和目錄。 舉一些例子,元數據包含與時間軸上的操作相關的更多元數據,並充當寫入端和讀取端的索引。 .heartbeat/
目錄存儲用於心跳管理的文件,而 .aux/
則保留用於各種輔助目的。
數據
Hudi將物理數據文件分爲Base File(基本文件)和Log File(日誌文件):
- 基本文件包含 Hudi 表中的主要存儲記錄,並針對讀取進行了優化。
- 日誌文件包含其關聯基本文件之上的記錄更改,並針對寫入進行了優化。
在 Hudi 表的分區路徑中(如前面的佈局圖所示),單個基本文件及其關聯的日誌文件(可以沒有或多個)被分組在一起作爲文件切片。 多個文件切片構成一個文件組。 文件組和文件切片都是邏輯概念,旨在封裝物理文件,從而簡化讀取端和寫入端的訪問和操作。 通過定義這些模型,Hudi 可以
- 滿足讀寫效率要求。 通常基本文件配置爲列式文件格式(例如 Apache Parquet),日誌文件設置爲基於行的文件格式(例如 Apache Avro)。
- 實現跨提交操作的版本控制。 每個文件切片都與時間軸上操作的特定時間戳相關聯,文件組中的文件切片本質上跟蹤所包含的記錄如何隨時間演變。
可以快速查看此處的 Hudi 表示例,瞭解數據佈局。
表格類型
Hudi 定義了兩種表類型 - 寫入時複製 (CoW) 和讀取時合併 (MoR)。 佈局差異如下:與 MoR 相比,CoW 沒有日誌文件,並且寫入操作會導致 .commit
操作而不是 .deltacommit
。 在我們的討論中,我們一直以 MoR 爲例。 一旦掌握了 MoR,理解 CoW 就變得簡單了 - 可以將 CoW 視爲 MoR 的特殊情況,其中基本文件中的記錄和更改在每次寫入操作期間隱式合併到新的基本文件中。 可以在此處瀏覽示例 CoW 表。
在爲 Hudi 表選擇表類型時,考慮讀取和寫入模式非常重要,因爲這會產生一些影響:
- 由於每次寫入都會重寫新文件切片中的記錄,因此 CoW 具有較高的寫入放大,而讀取操作始終會得到優化。 這非常適合讀取繁重的分析工作負載或小型表。
- MoR 的寫入放大較低,因爲更改會“緩衝”在日誌文件中,並進行批處理以合併和創建新的文件切片。 但是,讀取延遲會受到影響,因爲讀取最新記錄需要將日誌文件與基本文件進行實時合併。
用戶還可以選擇僅讀取 MoR 表的基本文件,以提高效率,同時犧牲結果的新鮮度。 我們將在接下來的帖子中詳細討論 Hudi 的不同閱讀模式。 隨着 Hudi 項目的發展,與從 MoR 表讀取相關的合併成本在過去的版本中得到了優化。 可以預見 MoR 將成爲大多數工作負載場景的首選表類型。
回顧
在零到一系列的第一篇文章中,我們探討了 Hudi 存儲格式的基本概念,以闡明元數據和數據在 Hudi 表中的結構。 我們還簡要解釋了不同的表類型及其權衡。 如概覽圖所示,Hudi 作爲一個綜合性 Lakehouse 平臺,提供不同維度的功能。 在接下來的九篇文章中,我將逐步介紹該平臺的其他重要方面。