數據湖| Hudi


 

1. Hudi核心概念

Hudi核心組件結構

通過Hudi客戶端把數據寫入Hudi, 寫入的時候有兩種方式:

  • COW(copy on write)寫時復制-java中的讀寫分離
  • MOR(merge on read)讀時合並 (讀數據的時候先合並,寫數據時寫到par文件中,有新增的寫到預寫日志log中)

Hudi提供了3種查詢數據的方式:

  • 讀優化(只讀取par文件-base文件)
  • 增量(不同數據版本之間的增量, 最新寫入表里的數據, 指定commit之后的數據)
  • 快照(每隔一段時間可以保留版本的數據; )

有序的時間軸Timeline元數據(增量管理數據版本, 方便回溯數據)

分層布局的數據文件(支持兩種: parquet列式存儲和avro行式存儲)

索引Index

 

Hudi原語

提供兩種原語(可理解為原子性,一旦開始就不能被中斷),使得除了經典的批處理之外,還可以在數據湖上進行流處理。這兩種原語分別是:

  • Update(Upsert)/Delete記錄(對單條數據):Hudi使用細粒度的文件/記錄級別索引來支持 Update/Delete記錄,同時還提供寫操作的事務保證。查詢會處理最后一個提交的快照, 並基於此輸出結果。
    • PB  萬億級別數據想修改其中一條,Hive把某個分區數據查出來然后更新單條數據再寫進去;

      delete,  插入時 標記這條數據commit的時間、標記是否刪除; update, 標記刪除true, 標記insert插入數據;

  • 變更流:Hudi對獲取數據變更提供了一流的支持:可以從給定的時間點獲取給定表中已 updated/inserted/deleted的所有記錄的增量流,並解鎖新的查詢姿勢(類別)。把 Hudi當作kafka用。
    • 增量變更數據流

 

Hudi表設計

時間

  • Arrival time: 數據到達 Hudi 的時間
  • commit time:提交時間
  • Event time: record 中記錄的時間

 

 

有序的時間軸元數據

TimeLine

Timeline原理

只要對數據有一些操作,Hudi就會把這些操作對應的元數據用時間軸Timeline的形式

維護起來,Timeline中記錄了每次操作, Instant可以理解為一個時間點

每個Instant里面包含: Action/ Time/ State

Action(表示當前的動作) 

  • COMMITS:寫完提交數據
  • CLEANS:刪除以前版本數據
  • DELTA_COMMIT:MOR寫數據方式, 提交了
  • COMPACTION:追加寫的日志進行合並統一一個par文件
  • ROLLBACK:回滾
  • SAVEPOINT:把當前commit數據版本保留起來

Hudi中的每個操作都是原子性的, Hudi保證了在時間軸上操作的原子性和基於Instant時間軸的一致性;

Time

  是Action產生的一些時間

State

  • Requested 動作剛發起;
  • Inflight 動作正在進行中;
  • Completed 動作已完成;

數據文件

FileManage

Huid的數據存儲在hdfs上, 分區partition

  FileGroup(邏輯上的概念)-對數據分桶

    一個FileSlice對應一個parquet文件

以HDFS存儲來看,一個Hudi表的存儲文件分為兩類: 

 

 Hudi真實的數據文件使用Parquet文件格式存儲

 

 .hoodie文件夾中存放對應操作的狀態記錄

Hoodie key

Hudi為了實現數據的CRUD,需要能夠唯一標識一條記錄。hudi將把數據集中的唯一字段(record key ) + 數據所在分區 (partitionPath) 聯合起來當做數據的唯一鍵

索引

Hoodie key (record key + partition path) 和 file id (FileGroup) 之間的映射關系,數據第一次寫入文件后保持不變,所以,一個 FileGroup 包含了一批 record 的所有版本記錄。

Index 用於區分消息是 INSERT 還是 UPDATE。

Index的創建過程

    BloomFilter Index

  • 新增 records 找到映射關系:record key => target partition
  • 當前最新的數據 找到映射關系:partition => (fileID, minRecordKey, maxRecordKey) LIST (如果是 base files 可加速)
  • 新增 records 找到需要搜索的映射關系:fileID => HoodieKey(record key + partition path) LIST,key 是候選的 fileID
  • 通過 HoodieKeyLookupHandle 查找目標文件(通過 BloomFilter 加速)

Hbase中使用布隆過濾器進行加速查找

Hudi的索引跟hbase比較像,它找數據時如果能夠內存中的布隆過濾器,

如果沒有就在磁盤中查找數據;

Hbase架構

 

 

2. Hudi的特性和功能

Hudi特性

• 效率的提升:支持CURD語義,支持增量處理,不再進行快照全量計算, 只處理有變更的記錄並且只重寫表中已更新/刪除的部分,而不是重寫整個表分區甚至整個表,為這些操作帶來一個數量級的性能提升

• 更快的ETL/派生Pipelines:自動進行准實時增量計算,不再使用Azkaban 等調度系統依賴觸發任務運行進行ETL處理

• 節省大量的計算資源成本

• 統一存儲引擎

Hudi功能

• 支持快速,可插拔索引的upsert();

• 高效、只掃描新數據的增量查詢

• 原子性的數據發布和回滾,支持恢復的Savepoint

• 具有mvcc(多版本並發控制)風格設計的讀和寫快照隔離;

• 已有記錄update/delta的自管理壓縮;

• 審核數據修改的時間軸元數據;

• 全狀態數據保留功能。

3. Hudi的存儲格式和查詢類型

Hudi存儲格式

Data - Hudi以兩種不同的存儲格式存儲所有攝取的數據。這塊的設計也是插件式的,用戶可選擇滿足下列條件 的任意數據格式:

  • 讀優化的列存格式(ROFormat)。缺省值為Apache Parquet
  • 寫優化的行存格式(WOFormat)。缺省值為Apache Avro

存儲格式的選型,判斷業務場景讀寫哪個多

 

Hudi表類型

COW:Copy On Write(寫時復制)

Copy On Write 類型表每次寫入都會生成一個新的持有 base file(對應寫入的 instant time ) 的 FileSlice。 用戶在 snapshot 讀取的時候會掃描所有最新的 FileSlice 下的 base file。

寫數據時,先復制一個版本往這個版本寫,讀數據時從復制之前的讀取;

 

MOR:Merge On Read(讀時合並)

讀時合並就是,base基准文件 插入新增,用寫日志的方式寫入;查詢時base + log文件合並查詢;

Merge On Read 表的寫入行為,依據 index 的不同會有細微的差別:

•對於 BloomFilter 這種無法對 log file 生成 index 的索引方案,對於 INSERT 消息仍然會寫 base file (parquet format),只有 UPDATE 消息會 append log 文件(因為 base file 已經記錄了該 UPDATE 消息的

FileGroup ID)。

•對於可以對 log file 生成 index 的索引方案,例如 Flink writer 中基於 state 的索引,每次寫入都是 log format,並且會不斷追加和 roll over。 Merge On Read 表的讀在 READ OPTIMIZED 模式下,只會讀最近的

經過 compaction 的 comm

 

 不同表如何加速

2種寫入的方式 * 3種讀查詢方式  = 6種方式

 

 Hudi選型結論

  • 1.兼容歷史數據倉庫及模型
  • 2.偏SQL分析,符合我司業務情況
  • 3.數據分析時效性更快,兼容presto+hive+spark
  • 4.數據存儲更完整,歷史快照版本管理,用戶可隨 意調用歷史任意時間段狀態數據

4. Hudi的企業級應用

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM