Hudi的更新機制

在深入研究Hudi機制之前,讓我們首先了解Hudi正在解決的問題。

客戶在使用數據湖時通常會問一個問題:當源記錄被更新時,如何更新數據湖?這是一個很難解決的問題,因爲一旦你寫了CSV或Parquet文件,唯一的選擇就是重寫它們,沒有一種簡單的機制可以打開這些文件,找到一條記錄並用源代碼中的最新值更新該記錄,當數據湖中有多層數據集時,問題變得更加嚴重,數據集的輸出將作爲下次數據集計算的輸入。

在數據庫中用戶只需發出一個更新記錄命令就可以完成任務了,所以從數據庫的思維模式來看很難理解上述限制,爲什麼不能在數據湖中完成?首先讓我們來看看數據庫是如何應用記錄級更新的,這對於理解Hudi是如何工作的很有價值。

RDBMS的更新原理

RDBMS將數據存儲在B-Tree存儲模型中,數據存儲在數據頁中,數據頁可以通過在表的列上創建的索引來找到。因此當發出更新命令時,RDBMS引擎會找到包含該記錄的確切頁面,並在該數據頁面中適當地更新數據,這是一個簡化的描述,在大多數現代RDBMS引擎中,在多版本併發控制等方面存在額外的複雜性,但基本思想保持不變。

下圖說明了如何通過B樹索引找到帶有值13的數據頁,底層(第三層)是表示數據頁的葉節點,頂層(第一層)和中間層(第二層)上的節點是索引值。

圖片

以下是一些非SQL數據庫(如Cassandra)中的更新工作方式:

許多非SQL數據庫將數據存儲在LSM樹的存儲模型中,這是一個基於日誌的存儲模型,新數據(插入/更新/刪除)被添加到append-only的日誌中,然後定期將日誌合併回數據文件,使數據文件與所有更改的數據保持最新,這種合併過程稱爲壓縮,因此當更新一條記錄時,只是將其寫入到append-only日誌中,根據數據庫引擎的優化規則,將組合append-only日誌和數據文件來爲讀取查詢提供服務,這也是一個簡化的描述,但基本思想相同。

下圖說明了如何將新的和更新的數據添加到append-only日誌(級別0)中,並最終合併到更大的文件中(級別1和級別2)。

圖片

現在我們已經基本瞭解了數據庫如何處理記錄級別的更新,接着看看Hudi如何工作,在Hudi(和類似的框架,如DeltaLake)出現之前,對datalake應用更新的唯一途徑是重新計算並重寫整個csv/parquet文件,如前所述,沒有簡單的機制來打開文件並更新其中的單個記錄,造成這種限制有很多原因,其中一些主要原因是不知道哪個文件包含要更新的記錄,也沒有有效的方法來掃描一個文件來找到想要更新的記錄,另外Parquet這樣的列文件格式不能就地更新,只能重新創建。在數據湖中,通常還有多個被轉換的數據層,其中一組文件被輸入到下一組文件的計算中,因此在單記錄更新期間編寫邏輯來管理這種依賴關係幾乎是不可能的。

HUDI

HUDI框架的基本思想是採用數據庫更新機制的概念,並將其應用於datalake,這就是Hudi實現的目標,Hudi有兩種“更新”機制:

  • 寫時拷貝(COW)-這類似於RDBMS B-Tree更新
  • 讀時合併(MOR)-這類似於No-SQL LSM-Tree更新

此外,HUDI還維護以下內容:

  • 將數據記錄映射到文件(類似於數據庫索引)
  • 跟蹤到數據湖中的每個邏輯表的最近提交
  • 能夠基於“record_key”在文件中識別單個記錄,這在所有Hudi數據集中是必需的,類似於數據庫表中的主鍵

Hudi使用上述機制以及“precombine_key”機制來保證不會存在重複的記錄。

  • 標準數據文件大小(儘可能)

Copy on Write

在該模型中,當記錄更新時,Hudi會找到包含更新數據的文件,然後使用更新值重寫這些文件,包含其他記錄的所有其他文件保持不變,因此更新的處理是快速有效的,讀取查詢通過讀取最新的數據文件來查看最新的更新,此模型適用於讀性能更爲重要的讀重負載,這種模型的缺點是突然的寫操作會導致大量的文件被重寫,從而導致大量的處理。

Merge on Read

在該模型中,當記錄更新時,Hudi會將它附加到數據湖表的日誌中,隨着更多的寫入操作進入,它們都會被附加到日誌中,通過從日誌和數據文件中讀取數據並將結果合併在一起,或者根據用戶定義的參數只從數據文件中讀取數據來服務讀取查詢,如果用戶希望實時查看數據,則從日誌中讀取數據;否則,如果指定爲read optimized表,則從數據文件中讀取數據,但數據可能已過時,Hudi會定期將日誌合併到數據文件中,以使它們保持最新狀態,這是配置爲根據用例需求定期運行的壓縮過程。

如果你的數據湖中有多層數據集,每一層都將其輸出作爲下一個計算的輸入,那麼只要所有這些數據集都是Hudi數據集,記錄級更新可以很好地、自動地在多個處理層中傳播,而不必重新編寫整個數據集。

以上所有這些都是從記錄更新的角度出發的,同樣的Hudi概念也適用於插入和刪除,對於刪除有軟刪除和硬刪除兩個選項,使用軟刪除,Hudi保留記錄鍵並刪除記錄數據,使用硬刪除,Hudi會爲整個記錄寫空白值,丟棄記錄鍵和記錄數據。

在深入研究Hudi機制之前,讓我們首先了解Hudi正在解決的問題。

客戶在使用數據湖時通常會問一個問題:當源記錄被更新時,如何更新數據湖?這是一個很難解決的問題,因爲一旦你寫了CSV或Parquet文件,唯一的選擇就是重寫它們,沒有一種簡單的機制可以打開這些文件,找到一條記錄並用源代碼中的最新值更新該記錄,當數據湖中有多層數據集時,問題變得更加嚴重,數據集的輸出將作爲下次數據集計算的輸入。

在數據庫中用戶只需發出一個更新記錄命令就可以完成任務了,所以從數據庫的思維模式來看很難理解上述限制,爲什麼不能在數據湖中完成?首先讓我們來看看數據庫是如何應用記錄級更新的,這對於理解Hudi是如何工作的很有價值。

RDBMS的更新原理

RDBMS將數據存儲在B-Tree存儲模型中,數據存儲在數據頁中,數據頁可以通過在表的列上創建的索引來找到。因此當發出更新命令時,RDBMS引擎會找到包含該記錄的確切頁面,並在該數據頁面中適當地更新數據,這是一個簡化的描述,在大多數現代RDBMS引擎中,在多版本併發控制等方面存在額外的複雜性,但基本思想保持不變。

下圖說明了如何通過B樹索引找到帶有值13的數據頁,底層(第三層)是表示數據頁的葉節點,頂層(第一層)和中間層(第二層)上的節點是索引值。

圖片

以下是一些非SQL數據庫(如Cassandra)中的更新工作方式:

許多非SQL數據庫將數據存儲在LSM樹的存儲模型中,這是一個基於日誌的存儲模型,新數據(插入/更新/刪除)被添加到append-only的日誌中,然後定期將日誌合併回數據文件,使數據文件與所有更改的數據保持最新,這種合併過程稱爲壓縮,因此當更新一條記錄時,只是將其寫入到append-only日誌中,根據數據庫引擎的優化規則,將組合append-only日誌和數據文件來爲讀取查詢提供服務,這也是一個簡化的描述,但基本思想相同。

下圖說明了如何將新的和更新的數據添加到append-only日誌(級別0)中,並最終合併到更大的文件中(級別1和級別2)。

圖片

現在我們已經基本瞭解了數據庫如何處理記錄級別的更新,接着看看Hudi如何工作,在Hudi(和類似的框架,如DeltaLake)出現之前,對datalake應用更新的唯一途徑是重新計算並重寫整個csv/parquet文件,如前所述,沒有簡單的機制來打開文件並更新其中的單個記錄,造成這種限制有很多原因,其中一些主要原因是不知道哪個文件包含要更新的記錄,也沒有有效的方法來掃描一個文件來找到想要更新的記錄,另外Parquet這樣的列文件格式不能就地更新,只能重新創建。在數據湖中,通常還有多個被轉換的數據層,其中一組文件被輸入到下一組文件的計算中,因此在單記錄更新期間編寫邏輯來管理這種依賴關係幾乎是不可能的。

HUDI

HUDI框架的基本思想是採用數據庫更新機制的概念,並將其應用於datalake,這就是Hudi實現的目標,Hudi有兩種“更新”機制:

  • 寫時拷貝(COW)-這類似於RDBMS B-Tree更新
  • 讀時合併(MOR)-這類似於No-SQL LSM-Tree更新

此外,HUDI還維護以下內容:

  • 將數據記錄映射到文件(類似於數據庫索引)
  • 跟蹤到數據湖中的每個邏輯表的最近提交
  • 能夠基於“record_key”在文件中識別單個記錄,這在所有Hudi數據集中是必需的,類似於數據庫表中的主鍵

Hudi使用上述機制以及“precombine_key”機制來保證不會存在重複的記錄。

  • 標準數據文件大小(儘可能)

Copy on Write

在該模型中,當記錄更新時,Hudi會找到包含更新數據的文件,然後使用更新值重寫這些文件,包含其他記錄的所有其他文件保持不變,因此更新的處理是快速有效的,讀取查詢通過讀取最新的數據文件來查看最新的更新,此模型適用於讀性能更爲重要的讀重負載,這種模型的缺點是突然的寫操作會導致大量的文件被重寫,從而導致大量的處理。

Merge on Read

在該模型中,當記錄更新時,Hudi會將它附加到數據湖表的日誌中,隨着更多的寫入操作進入,它們都會被附加到日誌中,通過從日誌和數據文件中讀取數據並將結果合併在一起,或者根據用戶定義的參數只從數據文件中讀取數據來服務讀取查詢,如果用戶希望實時查看數據,則從日誌中讀取數據;否則,如果指定爲read optimized表,則從數據文件中讀取數據,但數據可能已過時,Hudi會定期將日誌合併到數據文件中,以使它們保持最新狀態,這是配置爲根據用例需求定期運行的壓縮過程。

如果你的數據湖中有多層數據集,每一層都將其輸出作爲下一個計算的輸入,那麼只要所有這些數據集都是Hudi數據集,記錄級更新可以很好地、自動地在多個處理層中傳播,而不必重新編寫整個數據集。

以上所有這些都是從記錄更新的角度出發的,同樣的Hudi概念也適用於插入和刪除,對於刪除有軟刪除和硬刪除兩個選項,使用軟刪除,Hudi保留記錄鍵並刪除記錄數據,使用硬刪除,Hudi會爲整個記錄寫空白值,丟棄記錄鍵和記錄數據。

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