Upgrade to Pro — share decks privately, control downloads, hide ads and more …

本番のトラフィック量でHudiを検証して見えてきた課題

 本番のトラフィック量でHudiを検証して見えてきた課題

otfst_tokyo #4 登壇資料

Tomohiro Hashidate

October 18, 2024
Tweet

More Decks by Tomohiro Hashidate

Other Decks in Technology

Transcript

  1. Config (初期検証時) hoodie.index.type=SIMPLE hoodie.datasource.write.hive_style_partitioning=true hoodie.datasource.hive_sync.jdbcurl=jdbc:hive2://localhost:10000/ hoodie.datasource.hive_sync.database=default hoodie.datasource.hive_sync.table=output_table hoodie.datasource.hive_sync.partition_fields=partition_id hoodie.datasource.hive_sync.enable=true hoodie.parquet.compression.codec=zstd

    hoodie.datasource.compaction.async.enable=true hoodie.cleaner.commits.retained=5 # ...省略... hoodie.streamer.source.kafka.enable.commit.offset=true hoodie.archive.merge.enable=true hoodie.clustering.inline=true hoodie.clustering.inline.max.commits=4 hoodie.clustering.plan.strategy.sort.columns=key
  2. 実行コマンド spark-submit \ --conf spark.streaming.kafka.allowNonConsecutiveOffsets=true \ --class org.apache.hudi.utilities.streamer.HoodieStreamer /usr/lib/hudi/hudi-utilities-bundle.jar \

    --props s3://repro-config/hudi-kafka-source.properties \ # 上記properties --schemaprovider-class org.apache.hudi.utilities.schema.SchemaRegistryProvider \ --source-class org.apache.hudi.utilities.sources.AvroKafkaSource \ --source-ordering-field updated_at \ --target-base-path s3://repro-batch-store/experiment_data\ --table-type MERGE_ON_READ \ --target-table UserProfiles \ --enable-sync \ --continuous \ --op UPSERT
  3. 重要な設定項目 その1 hoodie.index.type : index方式の決定。初期検証時はSIMPLEだった。性能に大 きく影響するので詳細は後述する。 hoodie.datasource.write.partitionpath.field : hudiテーブルのパーティショ ンキーを指定する。

    hoodie.datasource.compaction.async.enable : HoodieStreamerによる書き込 み時に非同期Compactionを実行する。同じ書き込みプロセス内で実行されるが書 き込み自体はブロックしない。 hoodie.cleaner.commits.retained : cleanプロセスで削除せずに維持する直近の コミット数。commitの数であってdeltacommitの数ではないことに注意。
  4. 重要な設定項目 その2 hoodie.archive.merge.enable : hudiは一定以上commitが蓄積されると metadataを一つのファイルにまとめてアーカイブする。その時アーカイブファイ ルのマージを有効にするかどうか。S3の様な追記をサポートしないファイルシス テムだと小さいファイルが大量に出来る可能性があるのでそれをマージできるよ うにする。 hoodie.streamer.source.kafka.enable.commit.offset

    : Kafkaからデータを受 け取る時にConsumer Groupとしてgroup.idを登録して受信状況をcommitする。 この設定を有効にしておくと、Kafka側のconsumer lagの監視で遅延状況が監視 できる様になる。 hoodie.clustering.inline : 書き込み処理と同じプロセスで同期的にclustering 処理を行う。これは書き込み処理をブロックするが別途clusteringジョブを運用す る必要がなくなる。
  5. そもそもSIMPLE indexとは 公式のリファレンスによると以下の様に書かれている。 SIMPLE (default for Spark engines): This is

    the standard index type for the Spark engine. It executes an efficient join of incoming records with keys retrieved from the table stored on disk. It requires keys to be partition-level unique so it can function correctly. see. https://hudi.apache.org/docs/indexing
  6. SIMPLE indexを利用していた理由 公式リファレンスのIndex Strategyの項目における"Workload 3: Random updates/deletes to a dimension

    table"に該当したため。 初手から余りAdvancedな設定に手を出すべきではないと考え一旦リファレンスに則る ことにした。 結果的にはどうにもならなかったので、再度検討することになった。
  7. BUCKET indexの採用 最終的にBUCKET indexを採用することにした。 BUCKET: Utilizes bucket hashing to identify

    the file group that houses the records, which proves to be particularly advantageous on a large scale. To select the type of bucket engine—that is, the method by which buckets are created—use the hoodie.index.bucket.engine configuration option. これはレコードのキーをハッシュ関数にかけてバケット(つまりfile group)を特定し、 それをレコードの所在と判断する方式だ。O(1)で即レコードを特定できるので大幅な 書き込み対象lookupの高速化が狙える。
  8. BUCKET indexの詳細 BUCKET indexには二つの方式があり、それぞれSIMPLEとCONSISTENT_HASHINGに なる。 SIMPLE(default): This index employs a

    fixed number of buckets for file groups within each partition, which do not have the capacity to decrease or increase in size. It is applicable to both COW and MOR tables. Due to the unchangeable number of buckets and the design principle of mapping each bucket to a single file group, this indexing method may not be ideal for partitions with significant data skew. CONSISTENT_HASHING: This index accommodates a dynamic number of buckets, with the capability for bucket resizing to ensure each bucket is sized appropriately. This addresses the issue of data skew in partitions with a high volume of data by allowing these partitions to be dynamically resized. As a
  9. チューニング後の重要なコンフィグ差分 hoodie.index.type=BUCKET hoodie.index.bucket.engine=CONSISTENT_HASHING hoodie.bucket.index.hash.field=user_id hoodie.bucket.index.num.buckets=2 hoodie.bucket.index.min.num.buckets=1 hoodie.bucket.index.max.num.buckets=1024 # CONSISTENT_HASHING利用時はmetadataテーブルを利用できない hoodie.metadata.enable=false

    hoodie.storage.layout.type=BUCKET hoodie.compact.inline.max.delta.commits=10 hoodie.compaction.strategy=org.apache.hudi.table.action.compact.strategy.UnBoundedCompactionStrategy hoodie.streamer.kafka.source.maxEvents=40000000 hoodie.clustering.plan.strategy.max.num.groups=10000
  10. コンフィグ詳細 その1 hoodie.index.type=BUCKET , hoodie.index.bucket.engine=CONSISTENT_HASHING は CONSISTENT_HASHING方式でBUCKET indexを利用する設定になる。 現時点での制約としてmetadataテーブルと同時に有効にすることができないらしいの で、metadataテーブルを明示的にオフにする。

    hoodie.bucket.index.num.buckets はSIMPLE方式のバケッティングの時の固定バ ケット数の設定とCONSISTENT_HASHING方式における初期バケット数の両方の設定 値になる。 hoodie.bucket.index.[min,max].num.buckets はCONSISTENT_HASHINGのバケッ ト区分を再割り当てした時の最小のバケット数と最大のバケット数になる。データ量 の偏りに合わせて設定するのが良いだろう。 (上記の設定のmax値が1024になっているが、これは引っかからない様に非常に大きく した値なので今回利用したデータではこんなに大きな値は必要無かった。 )
  11. 検証結果 上記の設定で大体1回のdeltacommitのパフォーマンスは2000万レコード / 3minだっ た。 しかし、compactionの実行を全ファイル対象にすると凡そ15分ほど実行に時間がかか る。この処理時間は実行インターバルを短くしても余り短縮できない。 全体のスループットを平均して1秒ごとに均すと、 75000rpsぐらいのペースでレコー ドを書き込むことができる。但し、リアルタイムクエリが可能であってもcompaction

    中の15分はデータが更新できない時間帯が存在する。 書き込みペースとしては十分なパフォーマンスが出せるという結果が得られたが、リ アルタイムクエリが可能なクエリエンジンに制限がある状況では、実際に利用可能な データが得られるまでのリードタイムは最悪の場合45分程度とかなり長くなってしま う。