大數據Hadoop之——新一代流式數據湖平臺 Apache Hudi
一、概述
Hudi(Hadoop Upserts Deletes and Incrementals),簡稱Hudi,是一個流式數據湖平臺,支持對海量數據快速更新,內置表格式,支持事務的存儲層、 一系列表服務、數據服務(開箱即用的攝取工具)以及完善的運維監控工具,它可以以極低的延遲將數據快速存儲到HDFS或云存儲(S3)的工具,最主要的特點支持記錄級別的插入更新(Upsert)和刪除,同時還支持增量查詢。
- Apache Hudl本身不存儲數據,僅僅管理數據,借助外部存儲引擎存儲數據,比如HDFS;
- 此外,Apache Hudi也不分析數據,需要使用計算分析引擎,查詢和保存數據,比如Spark或Flink;
- 使用Hudi時,加載jar包,底層調用API,所以需要依據使用大數據框架版本,編譯Hudi源碼,獲取對應依賴jar包。
GitHub地址:https://github.com/apache/hudi
官方文檔:https://hudi.apache.org/cn/docs/overview
上圖從下到上,由左向右看
- hudi 底層的數據可以存儲到hdfs、s3、azure、alluxio等存儲。
- hudi 可以使用spark/flink 計算引擎來消費 kafka、pulsar 等消息隊列的數據,而這些數據可能來源于 app 或者微服務的業務數據、日志數據,也可以是 mysql 等數據庫的 binlog 日志數據。
- spark/hudi 首先將這些數據處理為 hudi 格式的 row tables (原始表),然后這張原始表可以被 Incremental ETL (增量處理)生成一張 hudi 格式的 derived tables 派生表。
- hudi 支持的查詢引擎有:trino、hive、impala、spark、presto 等。
- 支持 spark、flink、map-reduce 等計算引擎繼續對 hudi 的數據進行再次加工處理。
二、Hudi 架構
- 通過DeltaStreammer、Flink、Spark等工具,將數據攝取到數據湖存儲,可使用HDFS作為數據湖的數據存儲;
- 基于HDFS可以構建Hudi的數據湖;
- Hudi提供統一的訪問Spark數據源和Flink數據源;
- 外部通過不同引擎,如:Spark、Flink、Presto、Hive、Impala、Aliyun DLA、AWS Redshit訪問接口;
三、Hudi的表格式
Hudi提供兩類型表:寫時復制(Copy on Write,COW)表和讀時合并(Merge On Read,MOR)表。
- 對于 Copy-On-Write Table,用戶的 update 會重寫數據所在的文件,所以是一個寫放大很高,但是讀放大為 0,適合寫少讀多的場景。
- 對于 Merge-On-Read Table,整體的結構有點像 LSM-Tree,用戶的寫入先寫入到 delta data 中,這部分數據使用行存,這部分 delta data 可以手動 merge 到存量文件中,整理為 parquet 的列存結構。
1)Copy on Write(寫時復制)
簡稱COW,顧名思義,它是在數據寫入的時候,復制一份原來的拷貝,在其基礎上添加新數據。正在讀數據的請求,讀取的是最近的完整副本,這類似Mysql 的MVCC的思想。
優點:讀取時,只讀取對應分區的一個數據文件即可,較為高效;
缺點:數據寫入的時候,需要復制一個先前的副本再在其基礎上生成新的數據文件,這個過程比較耗時。
2)Merge On Read(讀時合并)
簡稱MOR,新插入的數據存儲在delta log 中,定期再將delta log合并進行parquet數據文件。讀取數據時,會將delta log跟老的數據文件做merge,得到完整的數據返回。下圖演示了MOR的兩種數據讀寫方式。
優點:由于寫入數據先寫delta log,且delta log較小,所以寫入成本較低;
缺點:需要定期合并整理compact,否則碎片文件較多。讀取性能較差,因為需要將delta log和老數據文件合并
3)COW vs MOR
COW表,用戶在 snapshot 讀取的時候會掃描所有最新的 FileSlice 下的 base file。
MOR表,在 READ OPTIMIZED 模式下,只會讀最近的經過 compaction 的 commit。
權衡 | 寫時復制(COW ) | 讀時合并(MOR ) |
數據延遲 | 更高 | 更低 |
更新代價( I/O) | 更高(重寫整個parquet文件) | 更低(追加到增量日志) |
Parque&件大小 | 更小(高更新代價( I/O) | 更大(低更新代價) |
寫放大 | 更高 | 更低(取決于壓縮策略) |
適用場景 | 寫少讀多 | 寫多讀少 |
四、元數據表(Metadata Table)
Apache Hudi元數據表可以顯著提高查詢的讀/寫性能。元數據表的主要目的是消除“列出文件”操作的要求。
讀取和寫入數據時,將執行文件列表操作以獲取文件系統的當前視圖。當數據集很大時,列出所有文件可能是性能瓶頸,但更重要的是,對于AWS S3等云存儲系統,由于某些請求限制,大量的文件列出請求有時會導致節流。相反,元數據表將主動維護文件列表,并消除遞歸文件列表操作的需要。
五、索引(Indexing)
Hudi通過索引機制將給定的hoodie鍵(記錄鍵+分區路徑)一致地映射到文件id,從而提供高效的升級。一旦將記錄的第一個版本寫入文件,記錄鍵和文件組/文件id之間的映射就不會改變。簡而言之,映射的文件組包含一組記錄的所有版本。
目前,Hudi支持以下索引類型:
Bloom索引(默認):使用由記錄鍵構建的Bloom過濾器,也可以使用記錄鍵范圍修剪候選文件。
簡單索引:根據從存儲上的表中提取的鍵,對傳入的更新/刪除記錄執行精簡聯接。
HBase索引:管理外部Apache HBase表中的索引映射。
自定義索引:當然也可以擴展這個公共API來實現自定義索引。
六、查詢類型(Query Type)
Hudi支持三種不同的查詢表的方式:Snapshot Queries(快照查詢)、Incremental Queries(增量查詢)和Read Optimized Queries(讀優化查詢)。
1)Snapshot Queries(快照查詢)
查詢查看給定提交或壓縮操作時表的最新快照。在合并讀取表的情況下,它通過動態合并最新文件切片的基本文件和增量文件來公開接近實時的數據(幾分鐘)。
對于隨寫復制表,它提供了現有拼花桌的插入式替換,同時提供了upsert/delete和其他寫入端功能。
2)Incremental Queries(增量查詢)
在給定的提交/壓縮之后,查詢只會看到寫入表的新數據。這有效地提供了更改流以啟用增量數據管道。
可查看自給定commit/delta commit即時操作依賴新寫入的數據,有效地提供變更流來啟用增量數據管道。
3)Read Optimized Queries(讀優化查詢)
查詢查看給定提交/壓縮操作時表的最新快照。僅顯示最新文件切片中的基/列文件,并確保與非hudi列表相比具有相同的列查詢性能。
讀優化查詢和快照查詢相同僅訪問基本文件,提供給定文件片自上次執行壓縮操作以來的數據。通常查詢數據的最新程度的保證取決于壓縮策略。
七、計算模型
在hudi過去的使用場景里,和大部分公司的架構類似,采用批式和流式共存的Lambda架構,后來Uber提出增量Incremental模型,相對批式來講,更加實時,相對流式而言,更加經濟。
1)批式模型(Batch)
批式模型就是使用MapReduce、Hive、Spark等典型的批計算引擎,以小時任務或者天任務的形式來做數據計算。特性如下:
延遲:小時級延遲或者天級別延遲。這里的延遲不單單指的是定時任務的時間,在數據架構里,這里的延遲時間通常是定時任務間隔時間+一系列依賴任務的計算時間+數據平臺最終可以展示結果的時間。數據量大、邏輯復雜的情況下,小時任務計算的數據通常真正延遲的時間是2-3小時。
數據完整度:數據較完整。以處理時間為例,小時級別的任務,通常計算的原始數據已經包含了小時內的所有數據,所以得到的數據相對較完整。但如果業務需求是事件時間,這里涉及到終端的一些延遲上報機制,在這里,批式計算任務就很難派上用場。
成本:成本很低。只有在做任務計算時,才會占用資源,如果不做任務計算,可以將這部分批式計算資源出讓給在線業務使用。從另一個角度來說成本是挺高的,如原始數據做了一些增刪改查,數據晚到的情況,那么批式任務是要全量重新計算。
2)流式模型(Stream)
流式模型,典型的就是使用Flink來進行實時的數據計算,特性:
延遲:很短,甚至是實時。
數據完整度:較差。因為流式引擎不會等到所有數據到齊之后再開始計算,所以有一個watermark的概念,當數據的時間小于watermark時,就會被丟棄,這樣是無法對數據完整度有一個絕對的保障。在互聯網場景中,流式模型主要用于活動時的數據大盤展示,對數據的完整度要求并不算很高。在大部分場景中,用戶需要開發兩個程序,一是流式數據生產流式結果,而是批式計算人物,用于次日修復實時結果。
成本:很高。因為流式任務時常駐的,并且對于多流join的場景,通常要借助內存或者數據庫來做state的存儲,不管是序列化開銷,還是和外部組件交互產生的額外IO,在大數據量下都是不容忽視的。
3)增量模型(Incremental)
針對批式和流式的優缺點,Uber提出了增量模型(Incremental Mode),相對批式來講,更加實時;相對流式而言,更加經濟。 增量模型,簡單來講,就是一mini batch的形式來跑準實時任務。hudi在增量模型中支持了兩個最重要的特性:
Upsert:這個主要是解決批式模型中,數據不能插入、更新的問題,有了這個特性,可以往Hive中寫入增量數據,而不是每次進行完全的覆蓋。(hudi自身維護了key-file的映射,所以當upsert時很容易找到key對應的文件)
Incremental Query:增量查詢,減少計算的原始數據量。以uber中司機和乘客的數據流join為例,每次抓取兩條數據流中的增量數據進行批式的join即可,相比流式數據而言,成本要降低幾個數量級。
八、數據倉庫 VS 數據湖
1)數據類型
結構化數據——來自關系型數據庫中的行和列。
半結構化數據——如CSV、日志、XML、JSON等。
非結構化數據——如email、文檔、PDF等。
二進制數據——如圖像、音頻、視頻等。
2)數據倉庫與數據湖的區別
數據倉庫可以理解為是一個優化的數據庫,用戶分析來自事物系統和業務線應用程序的關系型數據(結構化數據和半結構化數據)。
數據湖可以理解存儲來自業務應用程序的關系型數據(結構化數據),以及來自移動應用程序、IOT設備和社交媒體的非關系型數據(非結構化數據)等所有類型數據。
特性 | 數據倉庫 | 數據湖 |
數據 | 來自事務系統、運營數據庫和業務線應用程序的關系型數據 | 來自loT設備、網站、移動應用程序、社交媒體和企業應用程序的非關系型和關系型數據 |
Schema | 設計在超倉庫實施之前(寫入型Schema) | 寫入在分析時(讀取型Schema) |
性價比 | 更快的查詢結果會帶來更高的存儲成本 | 更快查詢結果只需較低存儲成本 |
數據質量 | 可作為重要事實依據的高度監管數據 | 任何可以或無法進行監管的數據(例如原始數據 |
用戶 | 業務分析師 | 數據科學家、數據開發人員和業務分析師(使用監管數據) |
分析 | 批處理報告、BI和可視化 | 機器學習、詢分析、數據發現和分析 |
3)湖倉一體化
Data Lakehouse (湖倉一體)是新出現的一種數據架構,它同時吸收了數據倉庫和數據湖的優勢,數據分析師和數據科學家可以在同一個數據存儲中對數據進行操作,同時它也能為公司進行數據治理帶來更多的便利性。
LakeHouse使用新的系統設計:直接在用于數據湖的低成本存儲上實現與數據倉庫中類似的數據結構和數據管理功能。
九、源碼編譯
編譯好的Hudi 包下載地址:
鏈接:https://pan.baidu.com/s/15qKm1kW1RRtbyFT53RoeGA?pwd=ihhb
提取碼:ihhb