Hudiは、データレイクのストレージ形式であり、Hadoopファイルシステム上でデータを更新および削除する機能と、変更されたデータをストリーミングする機能を提供します。
アプリケーションシナリオ
-
ほぼリアルタイムのデータ取り込み
Hudiは、データを挿入、更新、および削除する機能をサポートしています。メッセージキュー(Kafka)やログサービスSLSなどのログデータをHudiにリアルタイムで取り込むことができ、データベースBinlogによって生成された変更データのリアルタイム同期もサポートします。
Hudiは、データ書き込みプロセス中に生成される小さなファイルを最適化します。したがって、他の従来のファイル形式と比較して、HudiはHDFSファイルシステムに適しています。
-
ほぼリアルタイムのデータ分析
Hudiは、Hive、Spark、Presto、Impalaなどの複数のデータ分析エンジンをサポートしています。ファイル形式として、Hudiは追加のサービスプロセスに依存する必要がなく、使用がより軽量です。
-
インクリメンタルデータ処理
Hudiはインクリメンタルクエリクエリタイプをサポートしています。SparkStreamingを介して、特定のCOMMIT後に変更されたデータをクエリできます。Hudiは、HDFSデータの変更をストリーミングする機能を提供します。これは、既存のシステムアーキテクチャを最適化するために使用できます。
テーブルタイプ
Hudiは、次の2つのテーブルタイプをサポートしています。
-
コピーオンライト
特別な列ファイル形式(Parquet)を使用してデータを保存します。コピーオンライトテーブルの更新操作を書き直す必要があります。
-
読み取り時にマージ
データを格納するには、列ファイル形式(Parquet)と行ファイル形式(Avro)の混合方法を使用します。Merge On Readは、列形式を使用してベースデータを格納し、行形式を使用して増分データを格納します。新しく書き込まれた増分データは行ファイルに格納され、構成可能な戦略に従ってCOMPACTION操作が実行され、増分データが列ファイルにマージされます。
クエリタイプ
Hudiは、次の3つのクエリタイプをサポートしています。
-
スナップショットクエリ
COMMITの最新のスナップショットデータを照会できます。読み取り時にマージタイプのテーブルの場合、クエリ時に列ストレージのベースデータとログのリアルタイムデータをオンラインでマージする必要があります。書き込み時にコピーテーブルの場合、Parquetデータの最新バージョンをクエリできます。
コピーオンライトテーブルとマージオンリードテーブルは、このタイプのクエリをサポートしています。
-
インクリメンタルクエリ
インクリメンタルクエリをサポートする機能。特定のCOMMITの後に最新のデータをクエリできます。
このタイプのクエリをサポートしているのは、コピーオンライトテーブルのみです。
-
最適化されたクエリを読む
指定されたCOMMITの前に定義された範囲内の最新のデータのみを照会できます。読み取り最適化クエリは、Merge OnReadテーブルタイプのスナップショットクエリを最適化したものです。
コピーオンライトテーブルとマージオンリードテーブルは、このタイプのクエリをサポートしています。
データを書き込む
EMR-3.32.0以降のバージョンでは、Hudiサービスがデフォルトでサポートされているため、Hudiを使用する場合は、pomファイルにHudiの依存関係を追加するだけで済みます。
<dependency>
<groupId>org.apache.hudi</groupId>
<artifactId>hudi-spark_2.11</artifactId>
<version>0.6.0</version>
<scope>provided</scope>
</dependency>
データの書き込み例は次のとおりです。
-
データの挿入または更新
val spark = SparkSession .builder() .master("local[*]") .appName("hudi test") .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer") .getOrCreate() import spark.implicits._ val df = (for (i <- 0 until 10) yield (i, s"a$i", 30 + i * 0.2, 100 * i + 10000, s"p${i % 5}")) .toDF("id", "name", "price", "version", "dt") df.write.format("hudi") .option(TABLE_NAME, "hudi_test_0") // .option(OPERATION_OPT_KEY, UPSERT_OPERATION_OPT_VAL) //更新数据 .option(OPERATION_OPT_KEY, INSERT_OPERATION_OPT_VAL) //插入数据 .option(RECORDKEY_FIELD_OPT_KEY, "id") .option(PRECOMBINE_FIELD_OPT_KEY, "version") .option(KEYGENERATOR_CLASS_OPT_KEY, classOf[SimpleKeyGenerator].getName) .option(HIVE_PARTITION_EXTRACTOR_CLASS_OPT_KEY, classOf[MultiPartKeysValueExtractor].getCanonicalName) .option(PARTITIONPATH_FIELD_OPT_KEY, "dt") .option(HIVE_PARTITION_FIELDS_OPT_KEY, "ds") .option(META_SYNC_ENABLED_OPT_KEY, "true")//开启元数据同步功能 .option(HIVE_USE_JDBC_OPT_KEY, "false") .option(HIVE_DATABASE_OPT_KEY, "default") .option(HIVE_TABLE_OPT_KEY, "hudi_test_0") .option(INSERT_PARALLELISM, "8") .option(UPSERT_PARALLELISM, "8") .mode(Overwrite) .save("/tmp/hudi/h0")
-
データを削除する
df.write.format("hudi") .option(TABLE_NAME, "hudi_test_0") .option(OPERATION_OPT_KEY, DELETE_OPERATION_OPT_VAL) // 删除数据 .option(RECORDKEY_FIELD_OPT_KEY, "id") .option(PRECOMBINE_FIELD_OPT_KEY, "version") .option(KEYGENERATOR_CLASS_OPT_KEY, classOf[SimpleKeyGenerator].getName) .option(PARTITIONPATH_FIELD_OPT_KEY, "dt") .option(DELETE_PARALLELISM, "8") .mode(Append) .save("/tmp/hudi/h0")
データクエリ
HiveまたはPrestoがHudiテーブルにクエリを実行する場合、書き込みフェーズでメタデータ同期機能を有効にする必要があります(META_SYNC_ENABLED_OPT_KEYをtrueに設定します)。
コミュニティバージョンのHudiの場合、コピーオンライトテーブルとマージオン読み取りテーブルを設定して、hive.input.format = org.apache.hudi.hadoop.hive.HoodieCombineHiveInputFormatを設定する必要があります。コピーオンライトテーブルのEMRバージョンでは、フォーマットパラメータを設定する必要はありません。
Hudiの詳細については、https://hudi.apache.org/を参照してください。