@
Apache Hudi 官網地址 https://hudi.apache.org/
Apache Hudi 官網檔案 https://hudi.apache.org/docs/overview
Apache Hudi GitHub原始碼地址 https://github.com/apache/hudi
Apache Hudi是可以在資料庫層上使用增量資料管道構建流資料湖,滿足記錄級更新/刪除和更改流,並實現自我管理,支援流批一體並在此基礎上持續優化。最新版本為0.12.1
Apache Hudi(發音為「hoodie」)是下一代流資料湖平臺,將核心倉庫和資料庫功能引入資料湖中。Hudi提供了表、事務、高效的upsert /delete、高階索引、流攝入服務、資料叢集/壓縮優化和並行性,同時將資料保持為開原始檔格式,在分散式檔案儲存(雲端儲存,HDFS或任何Hadoop檔案系統相容的儲存)上管理大型分析資料集的儲存;不僅非常適合於流工作負載,還允許建立高效的增量處理管道;得益於其高階效能優化,使得分析工作能否較好的支援流行的查詢引擎如Spark、Flink、Presto、Trino、Hive。總體框架及周邊關係如下:
Apache Hudi是一個快速發展的多元化社群,下面為使用和貢獻Hudi的小部分公司範例:
元件版本
準備編譯環境Maven
# 可以在github中下載
wget https://github.com/apache/hudi/archive/refs/tags/release-0.12.1.tar.gz
# 解壓
tar -xvf release-0.12.1.tar.gz
# 進入根目錄
cd hudi-release-0.12.1/
<hadoop.version>3.3.4</hadoop.version>
<hive.version>3.1.3</hive.version>
<repositories>
<repository>
<id>nexus-aliyun</id>
<name>nexus-aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
mvn clean package -DskipTests -Dspark3.3 -Dflink1.15 -Dscala-2.12 -Dhadoop.version=3.3.4 -Pflink-bundle-shade-hive3
編譯報錯
try (FSDataOutputStream outputStream = new FSDataOutputStream(baos,null)) {
由於kafka-schema-registry-client-5.3.4.jar、common-utils-5.3.4.jar、common-config-5.3.4.jar、kafka-avro-serializer-5.3.4.jar這四個包一直沒有安裝成功,因此我們手動下載安裝到本地maven倉庫
# 下載confluent包
wget https://packages.confluent.io/archive/5.3/confluent-5.3.4-2.12.zip
# 解壓
unzip confluent-5.3.4-2.12.zip
# 通過find命令找到儲存位置
find share/ -name kafka-schema-registry-client-5.3.4.jar
# 安裝到本地maven倉庫
mvn install:install-file -DgroupId=io.confluent -DartifactId=common-config -Dversion=5.3.4 -Dpackaging=jar -Dfile=./share/java/confluent-common/common-config-5.3.4.jar
mvn install:install-file -DgroupId=io.confluent -DartifactId=common-utils -Dversion=5.3.4 -Dpackaging=jar -Dfile=./share/java/confluent-common/common-utils-5.3.4.jar
mvn install:install-file -DgroupId=io.confluent -DartifactId=kafka-schema-registry-client -Dversion=5.3.4 -Dpackaging=jar -Dfile=./share/java/confluent-control-center/kafka-schema-registry-client-5.3.4.jar
mvn install:install-file -DgroupId=io.confluent -DartifactId=kafka-avro-serialize -Dversion=5.3.4 -Dpackaging=jar -Dfile=./share/java/confluent-control-center/kafka-avro-serializer-5.3.4.jar
解決spark模組依賴衝突(修改了Hive版本為3.1.2,其攜帶的jetty是0.9.3,hudi本身用的0.9.4)存在依賴衝突
在hive-service中376行之後增加如下內容
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.pentaho</groupId>
<artifactId>*</artifactId>
</exclusion>
在hive-jdbc中排除下面依賴
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
在hive-metastore中排除下面依賴
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-core</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
在hive-commons中排除下面依賴
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>javax.servlet</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
增加Hudi依賴的jetty版本
<!-- 增加hudi設定版本的jetty -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
<version>${jetty.version}</version>
</dependency>
在hive-service中396行之後增加如下內容
<exclusion>
<artifactId>servlet-api</artifactId>
<groupId>javax.servlet</groupId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.pentaho</groupId>
<artifactId>*</artifactId>
</exclusion>
在hive-jdbc中排除下面依賴
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
在hive-metastore中排除下面依賴
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.datanucleus</groupId>
<artifactId>datanucleus-core</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet.jsp</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
在hive-commons中排除下面依賴
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>javax.servlet</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
增加Hudi依賴的jetty版本
<!-- 增加hudi設定版本的jetty -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
<version>${jetty.version}</version>
</dependency>
重新執行編譯命令,等待5~10分鐘時間
Hudi的核心是維護表上在不同時刻執行的所有操作的時間軸,這有助於提供表的瞬時檢視,同時還有效地支援按到達順序檢索資料。TimeLine是Hudi實現管理事務和其他表服務,一個Hudi瞬間由以下幾個部分組成:
Apache Hudi 檔案在儲存上的總體佈局方式如下:
原理:Hudi通過索引機制提供高效的upserts,具體是將hoodie key(record key+partition path)與檔案id(檔案組)建立唯一對映,對映的檔案組包含一組記錄的所有版本。
下圖中黃色塊為更新檔案,白色塊為基本檔案
索引的型別
全域性索引/非全域性索引
hoodie.index.type=GLOBAL_BLOOM
hoodie.index.type=GLOBAL_SIMPLE
索引的選擇策略
Hudi表型別定義瞭如何在DFS上對資料進行索引和佈局,以及如何在這種組織之上實現上述原語和時間軸活動(即如何寫入資料)。反過來,查詢型別定義瞭如何向查詢公開底層資料(即如何讀取資料)。Hudi表型別分為COPY_ON_WRITE(寫時複製)和MERGE_ON_READ(讀時合併)。
Copy On Write
當資料寫入寫入即寫複製表並在其上執行兩個查詢時
在讀表上合併的目的是支援直接在DFS上進行接近實時的處理,而不是將資料複製到可能無法處理資料量的專門系統。這個表還有一些次要的好處,比如通過避免資料的同步合併減少了寫量的增加,即在批次處理中每1個位元組的資料寫入的資料量。下面為兩種型別的查詢—快照查詢和讀取優化查詢的圖說明
CopyOnWrite | MergeOnRead | |
---|---|---|
資料延遲 | 高 | 低 |
查詢延遲 | 低 | 高 |
更新 (I/O)成本 | 高(重寫整個 parquet檔案) | 低 (追加到增量紀錄檔) |
Parquet 檔案大小 | 小 | 較大 |
寫擴大 | 高 | 低(依賴合併或壓縮策略) |
查詢型別:支援快照查詢、增量查詢、讀優化查詢三種查詢型別。
快照查詢:提供對實時資料的快照查詢,使用基於列和基於行的儲存的組合(例如Parquet + Avro)。針對全量最新資料COW表直接查最新的parquet檔案,而MOR表需要做一個合併(最新全量資料)。
增量查詢:提供一個更改流,其中包含在某個時間點之後插入或更新的記錄。可以查詢給定commit/delta commit即時操作以來新寫入的資料。有效的提供變更流來啟用增量資料管道(最新增量資料)。
讀優化查詢:通過純列儲存(例如Parquet)提供出色的快照查詢效能。可檢視給定的commit/compact即時操作的表的最新快照。僅將最新檔案片的基本/列檔案暴露給查詢,並保證與非Hudi表相同的列查詢效能(並不是全量最新),只是合併時檔案。
不同表支援查詢型別
Table Type | Supported Query types |
---|---|
Copy On Write | Snapshot Queries + Incremental Queries |
Merge On Read | Snapshot Queries + Incremental Queries + Read Optimized Queries |
不同查詢型別之間的權衡
快照 | 讀優化 | |
---|---|---|
資料延遲 | 低 | 高 |
查詢延遲 | 高 (合併基本檔案/列式檔案 + 基於行的 delta 紀錄檔檔案) | 低(行原始 / 列式檔案效能) |
**本人部落格網站 **IT小神 www.itxiaoshen.com