Apache Hudiの設計とアーキテクチャの最も強力な解釈

Apache Hudiの貢献者であるWang Xianghuの翻訳と貢献に感謝します。

WeChatパブリックアカウントに注目することを歓迎します:ApacheHudi

この記事では、Apache Hudiの基本的な概念、設計、および全体的なインフラストラクチャを紹介します。

1.はじめに

Apache Hudi(略称:Hudi)を使用すると、Hadoop互換ストレージに大量のデータを格納できます。また、従来のバッチ処理に加えて、データレイクでのストリーム処理を可能にする2つのプリミティブを提供します。2つのプリミティブは次のとおりです。

  • レコードの更新/削除:Hudiは、きめ細かなファイル/レコードレベルのインデックスを使用して、レコードの更新/削除をサポートすると同時に、書き込み操作のトランザクションを保証します。クエリは、最後に送信されたスナップショットをこの出力に基づいて処理します。

  • ストリームの変更:Hudiは、データの変更を取得するためのファーストクラスのサポートを提供します。特定の時点から更新/挿入/削除された特定のテーブル内のすべてのレコードの増分ストリームを取得し、新しいクエリポーズ(カテゴリ)をロック解除できます。

これらのプリミティブは密接に組み合わされて、DFS抽象化に基づくストリーミング/増分処理機能のロックを解除します。ストリーム処理に精通している場合、これはkafkaトピックからのイベントを消費し、状態ストレージを使用して中間結果を徐々に蓄積することに似ています。これには、アーキテクチャにおいて次の利点があります。1)効率の向上:データの取り込みは、通常、更新、削除を処理し、一意のキー制約を適用する必要があります。ただし、これらの機能の標準サポートを提供できるHudiのようなシステムがないため、データエンジニアはジョブの大規模なバッチを使用して1日のイベントを再処理するか、実行するたびにアップストリームデータベース全体をリロードし、結果として大きなコンピューティングリソースが無駄になっています。Hudiはレコードレベルの更新をサポートしているため、変更されたレコードのみを処理し、テーブルのパーティション全体またはテーブル全体を再書き込みするのではなく、変更されたレコードのみを処理して、テーブルの更新/削除された部分のみを再書き込みすることにより、これらの操作のパフォーマンスが大幅に向上します。2)より高速なETL /派生パイプライン:外部システムからデータを取り込んだ後の次のステップは、Apache Spark / Apache Hiveまたはその他のデータ処理フレームワークを使用して、これらのデータをデータウェアハウス、機械学習、または単なるデータ分析のためにETLすることですいくつかのアプリケーションシナリオを待ちます。通常、これらのプロセスは、コードまたはSQLで表現されたバッチジョブに依存します。これにより、すべての入力データがバッチ処理され、すべての出力結果が再計算されます。スナップショットクエリの代わりにインクリメンタルクエリを使用して1つ以上の入力テーブルをクエリすることにより、このようなデータパイプラインを大幅に高速化し、上記のように上流のテーブルからのインクリメンタルな変更のみを再度処理し、ターゲットの派生テーブルをアップサートまたは削除できます。3)新しいデータの取得:リソースを減らしてパフォーマンスを向上させることは一般的ではありません。結局のところ、パフォーマンス(クエリの待機時間など)を向上させるために、通常はより多くのリソース(メモリなど)を使用します。Hudiは、従来のデータセットの管理方法を根本的に排除し、バッチの増分処理に追加の利点をもたらしました。以前のデータレイクと比較して、パイプラインの実行時間が短くなり、データ配信が高速になります。4)統合ストレージ:上記の3つの利点に基づいて、既存のデータレイクでの処理がより高速で軽量になることで、ほぼリアルタイムのデータにアクセスするために特別なストレージやデータマートが不要になります。

2.設計原則

ストリーミングの読み取り/書き込み:Hudiは、データベース設計の原則とゼロからの設計を利用して、大規模なデータセットの入出力に適用し、ストリームを記録します。この目的のために、Hudiは、記録されたキーを、それが配置されているファイルの場所にすばやくマップできるインデックス実装を提供しています。同様に、Hudiは、出力データをストリーミングするために、特別な列を通じてレコードレベルのメタデータを追加および追跡します。これにより、すべての変更の正確な増分ストリームを提供できます。自己管理:Hudiは、ユーザーがデータの鮮度(書き込みフレンドリー)とクエリパフォーマンス(読み取り/クエリフレンドリー)に異なる期待を抱いている可能性があることに気付きました。これは、リアルタイムスナップショット、インクリメンタルストリーミングなど、3つのクエリタイプをサポートしています。純粋な列データ。Hudiはすべてのステップで、自己管理(プログラムの作成の並列処理の自動最適化やファイルサイズの維持など)と自己修復(失敗した送信の自動ロールバックなど)を行います。 :入力データをメモリにキャッシュして、ワークロードを分析します)。これらの組み込みの操作レバー/自己管理機能がない場合、これらの大規模パイプラインの運用コストは通常​​2倍になります。すべてがログです。Hudiには、ログのみのストレージシステムの原則を実装し、すべてのクラウドプロバイダーのデータをシームレスに管理できる、追加のみのクラウドデータフレンドリーなデザインもあります。
キーと値のデータモデル:作成に関して、Hudiテーブルはキーと値のペアのデータセットとしてモデル化され、各レコードには一意のレコードキーがあります。さらに、レコードキーには、レコードを分割して保存できるパーティションパスを含めることもできます。これは通常、インデックスクエリの検索スペースを削減するのに役立ちます。

3.テーブル設計

Hudiプロジェクトの主要な技術的動機を理解した後、Hudiシステム自体の設計について詳しく見ていきましょう。より高いレベルでは、Hudiテーブルの書き込みに使用されるコンポーネントは、サポートされている方法でApache Sparkジョブに埋め込まれ、DFS対応ストレージ上のHudiテーブルを表す一連のファイルを生成します。次に、一定の保証があれば、Apache Spark、Presto、Apache Hiveなどのクエリエンジンがテーブルにクエリを実行できます。Hudiテーブルの3つの主要コンポーネント:1)順序付きタイムラインメタデータ。データベースのトランザクションログに似ています。2)階層レイアウトのデータファイル:実際にテーブルに書き込まれたデータ。3)インデックス(複数の実装):指定されたレコードを含むデータセットをマップします。

Hudiは、基本データの書き込みとクエリを行う次の機能を提供します。これにより、大規模なデータレイクの重要なモジュールになります。1)高速でプラグ可能なインデックスのアップサートをサポートします(); 2)効率的で、新しいデータのみをスキャンしますボリュームクエリ; 3)アトミックデータのリリースとロールバック、保存されたセーブポイントのサポート; 4)mvcc(マルチバージョン同時実行制御)スタイルを使用して設計された読み取りと書き込みのスナップショット分離; 5)統計を使用してファイルサイズを管理する; 6)持っているレコードの更新/デルタによる自己管理圧縮; 7)データ変更のタイムラインメタデータ; 8)GDPR(一般データ保護規則)およびデータ削除機能に適合します。

3.1タイムライン

Hudiはその中心に、さまざまな時点でデータセットに対して実行されたすべての即時操作を含むタイムラインを維持し、テーブルのインスタントビューを提供すると同時に、到着順にデータ検索を効果的にサポートします。タイムラインは、データベースのREDO /トランザクションログに似ており、一連のタイムラインインスタンスで構成されています。Hudiは、タイムラインで実行される操作のアトミック性と、インスタントタイムに基づくタイムラインの一貫性を保証します。タイムラインは、テーブルのベースパスの下にある.hoodieメタデータフォルダー内の一連のファイルとして実装されます。具体的には、最新のインスタントが1つのファイルとして保存され、古いインスタントがタイムラインアーカイブフォルダーにアーカイブされて、ライターとクエリによってリストされるファイルの数が制限されます。Hudiタイムラインインスタントは、次のコンポーネントで構成されています:1)操作タイプ:データセットで実行された操作のタイプ; 2)インスタント時間:通常、インスタント時間はタイムスタンプ(例:20190117010349)で、操作の開始時間に基づいています順序は単調です; 3)インスタントステータス:インスタントの現在のステータス;各インスタントには、操作のステータスとインスタントのインスタントステータスの詳細を示すavroまたはjson形式のメタデータ情報があります。主要なインスタント操作タイプは次のとおりです。1)COMMIT:1つのコミットはレコードアトムのセットをデータセットに書き込むことを意味します; 2)CLEAN:データセットで不要になった古いファイルバージョンのバックグラウンドアクティビティを削除します; 3)DELTA_COMMIT:バッチ処理しますMergeOnReadストレージタイプのデータセットへのアトミックな書き込みを記録します。これらの一部またはすべては増分ログにのみ書き込むことができます。4)COMPACTION:Hudiの差分データ構造のバックグラウンドアクティビティを調整します。たとえば、行ベースのログから更新します。ファイルは列形式になります。内部的には、圧縮はタイムライン上の特別なコミットとして表示されます; 5)ROLLBACK:コミット/増分コミットが失敗してロールバックされたことを示し、書き込みプロセス中に生成されたすべての部分ファイルを削除します; 6)SAVEPOINT:特定のファイルグループは「保存済み」としてマークされているため、クリーンアッププログラムはグループを削除しません。災害/データ復旧の場合、タイムライン上の特定のポイントにデータセットを復元するのに役立ちます。 

3.2データファイル

Hudiは、DFSの基本パスの下にあるテーブルをフォルダー構造に編成します。テーブルがパーティション化されている場合、基本パスの下に他のパーティションがあります。これらのパーティションは、Hiveテーブルによく似たパーティションデータを含むフォルダーです。各パーティションは、ベースパスに対するパーティションパスによって一意に識別されます。各パーティション内で、ファイルはファイルグループに編成され、ファイルIDで一意に識別されます。各スライスには、基本的な列ファイル(* .parquet)と、特定のコミット時に生成された一連のログファイル(* .log *)が含まれます。これには、基本ファイルの生成以降の基本ファイルの挿入/更新が含まれます。 。HudiはMVCC設計を使用しています。圧縮操作はログと基本ファイルをマージして新しいファイルピースを生成し、クリーンアップ操作は未使用/古いファイルピースを削除してDFS上のスペースを再利用します。

 

3.3インデックス

Hudiは、インデックス作成メカニズムを通じて効率的なアップサート操作を提供します。これにより、レコードキーとパーティションパスの組み合わせがファイルIDにマッピングされます。このレコードキーとファイルグループ/ファイルIDの間のマッピングは、ファイルグループに書き込まれます最初からもう変わらない。つまり、このマッピングファイルグループには、ファイルのグループのすべてのバージョンが含まれています。Hudiは現在、3つのインデックス実装(HBaseIndex、HoodieBloomIndex(HoodieGlobalBloomIndex)、InMemoryHashIndex)を提供して、レコードを含むファイルIDにレコードキーをマップしています。これにより、テーブル内のすべてのレコードをスキャンしなくても、アップサートの速度を大幅に向上させることができます。Hudiインデックスは、パーティションレコードをクエリする機能に応じて分類できます。1)グローバルインデックス:レコードキーマップのファイルIDは、パーティション情報なしでクエリできます。たとえば、ライターはパーティションパスとしてnullまたは任意の文字列を渡すことができますが、インデックスは引き続きレコードの場所を見つけます。グローバルキーは、レコードキーがテーブル全体で一意であることが保証されている場合に非常に役立ちますが、クエリの使用量はテーブルのサイズに応じて機能的に増加します。2)非グローバルインデックス:グローバルインデックスとは異なり、非グローバルインデックスはパーティションパス(partitionPath)に依存します。指定されたレコードキーの場合、非グローバルインデックスは指定されたパーティションパスの下のレコードのみを検索します。これは、パーティションパスとレコードキーが常に同時に生成されるシナリオに適しています。同時に、クエリインデックスの消費はパーティションに書き込まれるデータセットのサイズにのみ関連するため、スケーラビリティが向上します。

4.テーブルの種類

4.1コピーオンライトテーブル

COWテーブルが書き込まれると、データはベースファイルに直接書き込まれます(寄木細工)はログファイルに書き込みません。したがって、COWテーブルのファイルスライスにはベースファイルのみが含まれます(寄木細工のファイルがファイルスライスを構成します)。このストレージ方式のSpark DAGは比較的簡単です。重要な目標は、パーティショナーを使用して、タグ付きHudiレコードRDD(いわゆるタグ付きインデックスインデックスを参照し、テーブル内の各入力レコードの位置をマークする)を一連の更新と挿入に分割することです。ファイルサイズを維持するために、最初にワークロードプロファイルを取得するためのサンプリングでは、このプロファイルは、入力レコードの挿入と更新、およびパーティション内の分散とその他の情報を記録します。新しい方法でこのようにデータをパックします。1)更新の場合、ファイルIDの最新バージョンが1回書き換えられ、変更されたすべてのレコードに新しい値が使用されます。2)挿入の場合。レコードは最初に各パーティションパスにパックされます。最小のファイルで、構成された最大サイズに達するまで。その後の残りのすべてのレコードは、新しいファイルグループに再度パッケージ化され、新しいファイルグループは最大ファイルサイズ要件も満たします。 

 

4.2読み取り表にマージ

MORテーブルにデータを書き込むとき、レコードは最初にログファイルにすばやく書き込まれ、後でタイムラインの圧縮操作を使用してベースファイルとマージされます。クエリがログのマージされたスナップショットストリームまたは変更ストリームを読み取るか、マージされていないベースファイルのみを読み取るかに応じて、MORテーブルは複数のクエリタイプをサポートします。高レベルでは、MORライターは、データを読み取るときにCOWライターと同じステージを通過します。これらの更新は最新ファイルの最新ログファイルに追加され、マージされません。挿入の場合、Hudiは2つのモードをサポートします。1)ログファイルに挿入:インデックス可能なログファイルを含むテーブルがこの操作を実行します(HBaseインデックス)。2)寄木細工のファイルを挿入:インデックスファイルのないテーブル(ブルームインデックスなど)およびコピーオンライト(COW)と同様に、マークされた場所の入力レコードはパーティション化されるため、同じファイルIDに送信されたすべてのアップサートがグループ化されます。このアップサートのバッチは、1つ以上のログブロックとしてログファイルに書き込まれます。Hudiでは、クライアントがログファイルのサイズを制御できます。HudiのWriteClientは、コピーオンライト(COW)ライターとマージオンリード(MOR)ライターで同じです。数回のデータ書き込みにより、1つ以上のログファイルが蓄積されます。これらのログファイルは、基本的な寄木細工のファイル(存在する場合)と共にファイルスライスを形成し、このファイルスライスはファイルの完全なバージョンを表します。この種類のテーブルは、最も用途が広く、最も進んだテーブルです。書き込み(バースト書き込みトラフィックを吸収するためにさまざまな圧縮戦略を指定できます)およびクエリ(データの鮮度とクエリパフォーマンスの比較など)に優れた柔軟性を提供します。同時に、動作中の彼を制御するための学習曲線が含まれています。 

 

5.デザインを書く

5.1書き込み操作

Hudiデータソースまたはdeltastreamerツールによって提供される3つの異なる書き込み操作と、それらを最適に使用する方法を理解することが役立つ場合があります。これらの操作は、データセットに対して発行される各コミット/デルタコミットで選択/変更できます。1)Upsertオペレーション:これはデフォルトのオペレーションです。このオペレーションでは、インデックスをクエリすることにより、データレコードに挿入または更新のマークを付け、次にヒューリスティックを実行して、ストレージにパッケージ化してファイルサイズを最適化する方法を決定します。そして最後にレコードを書きます。データベース変更キャプチャなどの使用例では、入力にほぼ確実に更新が含まれている場合にこのアクションを使用することをお勧めします。2)挿入操作:upsertと比較して、挿入操作もヒューリスティックを実行してパッケージ化方法を決定し、ファイルサイズを最適化しますが、インデックスクエリは完全にスキップします。したがって、ログの重複排除などのユースケース(下記のフィルター複製オプションと組み合わせた場合)では、アップサートよりもはるかに高速です。これは、データセットが重複を許容できるユースケースにも当てはまりますが、Hudiに必要なのは、トランザクションの書き込み/増分プル/ストレージ管理機能のみです。3)一括挿入操作:upsertとinsertの両方の操作により、入力レコードがメモリに保持され、ストレージヒューリスティック計算の速度が向上します。そのため、Hudiデータセットのロード/ブートの最初の使用例では扱いにくい場合があります。一括挿入は、挿入と同じセマンティクスを提供し、並べ替えに基づくデータ書き込みアルゴリズムも実装します。これにより、数百テラバイトの初期負荷を十分に拡張できます。ただし、これはファイルサイズを調整するための最善の努力であり、挿入や更新などのファイルサイズを保証するものではありません。

5.2圧縮

圧縮は瞬時の操作であり、一連のファイルスライスを入力として受け取り、各ファイルスライスのすべてのログファイルをそのベースファイルファイル(寄木細工のファイル)とマージして、新しい圧縮ファイルスライスを生成し、それをタイムラインに1つとして書き込みます。コミット。圧縮は、読み取り時にMORテーブルタイプにのみ適用され、圧縮戦略(デフォルトでは、圧縮されていないログが最も大きいファイルスライスを選択)により、圧縮するファイルスライスを選択します。この圧縮戦略は、各書き込み操作の後に評価されます。高レベルでは、2つの圧縮方法があります。1)同期圧縮:ここでの圧縮は、各書き込み後にライタープロセス自体によって同期的に実行されます。つまり、次の書き込み操作は、圧縮が完了するまで開始できません。個別の圧縮プロセスを用意する必要がないため、操作の点ではこれが最も簡単ですが、データの鮮度は最低に保証されます。ただし、遅い/古いパーティションの圧縮を遅らせながら、各書き込み操作で最新のテーブルパーティションを圧縮できる場合、この方法は非常に役立ちます。2)非同期圧縮:このようにして、圧縮プロセスはテーブル書き込み操作と非同期で実行できます。これには、圧縮によってデータ書き込みの次のバッチがブロックされないため、ほぼリアルタイムでデータの鮮度が向上するという明らかな利点があります。Hudi DeltaStreamerなどのツールは、境界の連続モードをサポートしています。このモードでは、単一のSparkランタイムクラスターで圧縮および書き込み操作が実行されます。

5.3クリーンアップ

クリーンアップは基本的な即時操作であり、その目的は、古いファイルを削除し、テーブルが占有するストレージスペースを制限することです。クリーンアップは各書き込み操作の後に自動的に実行され、タイムラインサーバーにキャッシュされたタイムラインメタデータを使用して、テーブル全体をスキャンしてクリーンアップの機会を評価しないようにします。Hudiは2つのクリーニング方法をサポートしています。1)コミット/デルタコミットによるクリーニング:これは最も一般的であり、インクリメンタルクエリで使用する必要があります。このようにして、Cleanerは最後のNコミット/デルタコミットで書き込まれたすべてのファイルスライスを保持するため、あらゆる範囲内でインクリメンタルクエリを実行する機能を効果的に提供します。これはインクリメンタルクエリに非常に役立ちますが、構成範囲内のファイルフラグメントのすべてのバージョンが保持されるため、特定の高書き込み負荷シナリオでは、より多くのストレージスペースが必要になる場合があります。2)予約されたファイルスライスによるクリーンアップ:これはより簡単なクリーニング方法です。ここでは、各ファイルグループの最後のN個のファイルスライスのみを保存します。Apache Hiveなどの一部のクエリエンジンは、非常に大きなクエリを処理します。これらのクエリは、完了するまでに数時間かかる場合があります。この場合、Nを十分に大きくして、クエリがまだアクセスできるファイルを削除しないようにします。このフィルムはとても役に立ちます。さらに、クリーンアップ操作により、各ファイルグループの下に常に1つのファイルスライス(最新のスライス)のみが存在するようになります。

5.4 DFSアクセスの最適化

Hudiは、テーブルに格納されたデータに対していくつかの主要なストレージ管理機能も実行します。DFSにデータを保存するための鍵は、ファイルサイズを管理し、ストレージスペースをカウントして再利用することです。たとえば、HDFSは小さなファイルを処理することで悪名高く、NameNodeに対するメモリ/ RPCのプレッシャーはクラスター全体の安定性を損なう可能性があります。一般に、クエリエンジンは、適切なサイズの列ファイルでパフォーマンスを向上させることができます。これは、クエリエンジンが列の統計情報を取得するコストなどを効果的に償却できるためです。一部のクラウドデータストアでも、多数の小さなファイルを含むディレクトリを一覧表示すると、コストが発生します。Hudiの効率的な書き込み、データストレージ方法の管理は次のとおりです。1)小さなファイルの処理機能は、入力ワークロードを分析し、新しいファイルグループを作成する代わりに既存のファイルグループにコンテンツを分散します(これにより、小さなファイルが生成されます) )。2)ライターでタイムラインキャッシュを使用します。これにより、Sparkクラスターが毎回再起動しない限り、以降の書き込み操作でDFSディレクトリをリストして、指定したパーティションパスの下のファイルスライスのリストを取得する必要がなくなります。3)ユーザーは、基本ファイルとログファイルのサイズの比率係数と目的の圧縮率を調整して、十分な数の挿入を統合ファイルグループに分割し、適切なサイズの基本ファイルを生成することもできます。4)一括挿入の並列度をインテリジェントに調整し、初期ファイルグループを適切なサイズで再度調整できます。実際、ファイルグループは一度作成すると削除できず、上記の方法でのみ拡張できるため、この操作を正しく実行することが重要です。

6.お問い合わせ

この柔軟で包括的なデータレイアウトと豊富なタイムラインを考慮して、Hudiはテーブルのタイプに応じて、3つの異なる方法でテーブルをクエリできます。

クエリの種類 MOR
スナップショットクエリ クエリは、特定のテーブルまたはテーブルパーティションのすべてのファイルスライスの最新の基本ファイルに対して実行され、送信された最新のレコードが表示されます。 特定のテーブルまたはテーブルパーティション内のすべてのファイルスライス内の最新の基本ファイルとログファイルを組み合わせてクエリを実行すると、最新のデルタコミット操作によって書き込まれたレコードが表示されます。
インクリメンタルクエリ 指定された開始および終了インスタント時間範囲で、クエリは最新の基本ファイル(インクリメンタルクエリウィンドウと呼ばれます)に対して実行され、Hudiによって指定された列のみがこのウィンドウに書き込まれたレコードの抽出に使用されます。 クエリは、ウィンドウ自体、基本ブロックまたはログブロックのレコードの読み取りの組み合わせに応じて、インクリメンタルクエリウィンドウの最新のファイルスライスに対して実行されます。
最適化されたクエリを読み取る スナップショットクエリと同じ 基本ファイルのみにアクセスし、最後の圧縮操作以降の特定のファイルスライスのデータを提供します。通常、最新のクエリデータの保証は圧縮戦略に依存します

 

 

6.1スナップショットクエリ

特定のデルタコミットまたは即時コミット操作のコミット後のテーブルの最新のスナップショットを表示できます。読み取り時マージ(MOR)テーブルの場合、最新のファイルスライスの基本ファイルと増分ファイルを即座にマージすることにより、ほぼリアルタイムのテーブル(数分)を提供します。コピーオンライト(COW)の場合、既存の寄木細工のテーブル(または同じ基本ファイルタイプのテーブル)を置き換えることができ、アップサート/削除およびその他の書き込み機能を提供します。

6.2増分クエリ

特定のコミット/デルタコミットの即時操作以降、新しく書き込まれたデータを表示できます。変更ストリームを効果的に提供して、増分データパイプラインを有効にします。

6.3最適化されたクエリの読み取り

特定のコミット/コンパクト即時操作のテーブルの最新のスナップショットを表示できます。最新のドキュメントの基本/列ファイルのみがクエリに公開され、非Hudiテーブルと同じ列クエリのパフォーマンスが保証されます。

索引 最適化されたクエリを読み取る スナップショットクエリ
データ遅延 高い
クエリの遅延 高い

  

おすすめ

転載: www.cnblogs.com/leesf456/p/12710118.html