ファイルキャッシュの内部構造
基本原理
(1) キャッシュスライシングとプリフェッチ機構
Dorisは、データキャッシュ管理と読み取り効率を最適化するために、キャッシュスライシングとプリフェッチ機構を採用しています。具体的には、対象ファイルを1MBアライメントでスライスし、完全ダウンロード後に各スライスを個別のBlockファイルとしてローカルファイルシステムに保存します。このスライシング手法により、キャッシュ粒度を効果的に削減し、キャッシュの柔軟性と領域利用率を向上させています。Dorisは必要なデータ部分のみをキャッシュすることで、大きなファイル全体をキャッシュすることによる領域の無駄を回避できます。また、小さなキャッシュブロックは管理と退避を容易にし、より精密なホットスポットデータアクセスを可能にします。
(2) ローカルファイルディレクトリ構成
キャッシュされたデータをより適切に管理するために、Dorisは特定のローカルファイルディレクトリ構造を採用しています。キャッシュは複数のディスクの複数のディレクトリに分散される可能性があります。ディレクトリ間の均等な分散を実現するため、Dorisは対象ファイルパスからハッシュ値を計算し、このハッシュをBlockファイル格納の最下位レベルディレクトリとして使用します。各Blockファイルは、対象ファイル内でのオフセット位置に基づいて命名されます。
例えば、対象ファイルパスが/remote/data/datafile1でハッシュ値が12345の場合、キャッシュされたBlockファイルは/cache/123/12345/offset1に格納される可能性があります。ここでoffset1は元のファイル内でのブロックのオフセット位置を表します。
(3) マルチキュー機構
Dorisのファイルキャッシュは、異なるデータタイプを分離し、キャッシュ汚染を防止してヒット率を向上させるために、マルチキュー機構を使用しています。キャッシュデータは以下のタイプに分類され、それぞれ重要度によって優先順位付けされた個別のキューに格納されます:
- TTL Queue: TTL(Time-To-Live)属性を持つデータを格納します。このデータは指定されたTTL期間中キャッシュに残り、その期間中は最高優先度を持ちます。キャッシュ領域が不足している場合、システムはTTLデータを保持するために他のキューからデータを優先的に退避します。TTLはテーブル属性です。例えば3600に設定すると、このテーブルにインポートされたデータはインポート後1時間ファイルキャッシュに残る必要があります。使用例:長いTTL値を持つレジデントテーブルなど、ローカル永続化が必要な小規模テーブルに適しています。
- Index Queue: 主にクエリフィルタリング操作を加速するために使用されるインデックスデータを格納し、通常はアクセス頻度が高いです。注意:逆インデックスファイルは「インデックス」であるにも関わらず、通常サイズが大きいため、通常のキャッシュデータとして扱われます。
- Normal Queue: TTL属性を持たない通常データを格納します。ほとんどのデータはこのカテゴリに該当します。
- Disposable Queue: コンパクション読み取りなどの一時データを格納します。このデータは通常使用後に退避され、最低優先度を持ちます。
このマルチキュー機構により、Dorisは異なるデータ特性と使用シナリオに基づいてキャッシュ領域を合理的に割り当て、キャッシュリソース利用率を最大化できます。
(4) 退避機構
キャッシュ退避機構はファイルキャッシュ管理において重要であり、領域が制限された際にどのデータを退避対象として選択するかを決定します。Dorisの退避機構には以下のトリガーと選択戦略が含まれます:
退避トリガー:
- 領域制約による受動的退避:
- ローカルディスク領域またはinode数が不足している場合、Dorisは領域を解放するために受動的退避をトリガーします。
- キャッシュ容量制限に到達した場合:ディスク領域が残っていても、キャッシュ使用量が事前定義された閾値に達すると退避が開始されます。
- プロアクティブ早期退避:新しいデータが古いデータの退避を待つ必要がある同期退避とは異なり(クエリパフォーマンスに影響)、Dorisは使用量が高水位マークに達した際に古いキャッシュを非同期でクリーンアップします。
- プロアクティブガベージコレクション:LRUは未使用データを退避できますが、Dorisはコンパクション/Schema Change元データ、失敗したインポートロールバックデータ、削除されたテーブル/パーティションデータなどのガベージデータを積極的にクリーンアップします。
- TTL有効期限:TTLデータ固有です。TTLが期限切れになると、データは通常キャッシュに降格され、通常の退避に参加します。
退避対象選択:
- 退避比率:キューは個別の比率制限を持つディスク領域を共有します。領域が豊富な場合(他のキューが比率に達していない)、キューは残りの領域すべてを使用できます。例えば、通常キャッシュは総領域の40%に制限される場合がありますが、他のデータが存在しない場合は利用可能な領域すべてを使用できます。他のキューデータが入ると、比率は徐々に事前設定値に近づきます。
- 退避順序:書き込みキャッシュ領域が不足している場合、Dorisはこの順序でデータを退避します:Disposable → Normal → Index → TTL。他のキューデータを退避してもまだ十分な領域が解放されない場合、同一キュータイプ内でLRU退避が発生します。
退避回避推奨事項:
- 十分なディスク領域:キャッシュデータを収容するのに十分な領域を確保し、領域制約による頻繁な退避を回避します。キャッシュクリーンアップには遅延があるため、ある程度のバッファを維持してください。経験上、ファイルキャッシュ領域はクエリホットデータサイズの約1.5倍が最適なヒット率のために必要です。
- 大規模クエリの分離:大規模クエリを個別のクラスターにルーティングし、キャッシュ領域を占有して他のクエリのヒット率に影響することを防ぎます。
(5) ウォームアップ機構
キャッシュウォームアップは、後続のクエリを加速するためにデータをキャッシュに事前ロードします。Dorisは複数のウォームアップアプローチを提供します:
- 手動ウォームアップ:ユーザーは特定のテーブル/パーティションに対して現在のクラスターキャッシュをウォームアップしたり、別のクラスターを参照してそのキャッシュされたテーブル/パーティションをウォームアップできます。ウォームアップは常にリモートストレージからダウンロードします(他のクラスター/BEからではない)。実行後、ターゲット(テーブル/パーティションまたは参照クラスター)はBEダウンロード用のタブレットセットに変換されます。BEダウンロードロジックは基本的に、すべてのタブレットデータファイルをローカルにキャッシュするためのシーケンシャル読み取りを実行します。ウォームアップデータ量は大きくなる可能性があるため、Dorisはタスクを最大20GBのバッチに分割し、中断後の復旧のためのチェックポイントを設けます。BEで深刻な問題(クラッシュなど)が発生したり、ユーザーがウォームアップをキャンセルした場合、すべてのBEがダウンロードを停止します。ユーザーは
SHOW WARM UP JOB経由でジョブステータス(FINISHED、CANCELLED、RUNNING)を確認でき、実行中のジョブの進行状況も含まれます。同じテーブル/パーティションの反復ウォームアップは既存データを再ダウンロードせず、インクリメンタル更新のみを実行します。 - ロードバランシング起動ウォームアップ:タブレット分散が不均衡になった場合(特にノード障害やスケーリング中)、タブレットは新しいBEに移行します。ターゲットBEは、ソースBEからのメタデータ(利用可能な場合)を使用してキャッシュデータをダウンロードし、新しいノードでのクエリキャッシュヒットを保証します。ソースBEキャッシュデータはクリーンアップ中に積極的に退避されます。注意:移行と完全ダウンロードの間にはキャッシュミスが発生する可能性のある時間窓があります。
- クロスクラスター自動ウォームアップ(v3.1+):コンピュート-ストレージ分離シナリオでは、ユーザーはコンピュートクラスター間の自動キャッシュ同期を望む場合があります(例:インポートがクラスターAで発生するがクエリがクラスターBで実行される場合)。Dorisは2つの自動同期方法を提供します:
- 定期ウォームアップ:リアルタイム要件がない場合、
WARM UPSQLに同期間隔を追加します。一度きりの実行ではなく、タスクは指定されたテーブル/パーティションを一つのクラスターから別のクラスターに定期的にインクリメンタル同期します。 - インポート/コンパクション起動ウォームアップ:リアルタイム要件の場合、インポート完了イベントを使用してウォームアップをトリガーします。タブレットがクラスター間で異なって分散される可能性があるため、FEはターゲットクラスタータブレット分散についてソースクラスターに通知します。ソースクラスターインポートコミットフェーズ中に、新しくインポートされたリモートストレージデータをダウンロードするためにターゲットクラスターBEに通知します。コンパクションはウォームアップのために類似の通知パスに従います。
- 定期ウォームアップ:リアルタイム要件がない場合、
シナリオ分析
(1) クエリ処理におけるファイルキャッシュ
クエリ中、ファイルキャッシュはリモートストレージアクセスを削減し、データ取得を加速します:
- Scannerがデータファイルを読み取り:クエリが到着すると、Scannerは必要なデータファイルの読み取りを試みます。
- ローカルキャッシュチェック:リモートストレージにアクセスする前に、Scannerはまずローカルファイルキャッシュをチェックします。
- キャッシュヒット:キャッシュメタデータに要求されたファイルパスとオフセットが含まれている場合、Scannerがリモートダウンロードを回避して直接読み取るためのBlockFileハンドルを返し、遅延を削減します。
- キャッシュミス:部分的または完全にキャッシュされていない範囲に対して、Scannerはリモートストレージから不足データをダウンロードします。ダウンロードされたデータは退避ポリシーに従いながら、将来のクエリのためにファイルキャッシュに入ります。
(2) データロードにおけるファイルキャッシュ
インポート中、ファイルキャッシュは後続のクエリのためにデータを準備します:
- リモートストレージへのデータアップロード:インポートされたデータは最初にリモートストレージに送られます。
- 非同期ローカルキャッシュ書き込み:Dorisはこのデータをローカルディスクキャッシュに非同期で書き込み、インポート後クエリの即座のキャッシュヒットを可能にします。
- キャッシュタイプ:データタイプと属性(TTLなど)に基づいて、インポートされたデータは対応するキュー(TTL、Index、またはNormal)に入ります。
(3) コンパクションにおけるファイルキャッシュ
コンパクションは小さなファイルをマージしてストレージとクエリパフォーマンスを最適化します。Dorisには2つのタイプがあります:
- Cumulative Compaction:インクリメンタルデータバージョンをマージ
- Base Compaction:ベースラインデータ(バージョン0)とインクリメンタルバージョンをマージ
コンパクション中のキャッシュ処理:
- Cumulative Compaction:新しくマージされたデータは、リモートストレージアップロード後にファイルキャッシュに入り、インポートと同様に後続のクエリを加速します。
- Base Compaction:Base Compactionは通常大きなコールドデータを含むため、新しいデータは領域が許可する場合のみキャッシュに入ります。ユーザーはBE設定
enable_file_cache_keep_base_compaction_output = true経由で強制キャッシュ挿入が可能ですが、これは他のホットデータを退避する可能性があります。将来のバージョンでは、キャッシュ挿入を決定するために履歴クエリ統計を使用する適応戦略を計画しています。
(4) 再起動後のキャッシュロード
再起動後のキャッシュロードは、キャッシュ状態復旧と迅速なクエリ応答のために重要です。v3.1以前では、保持されないLRU情報がキューの順序不整合を引き起こし、ヒット率に影響していました。
v3.1はLRU永続化を導入しています:
- 定期ダンプ:DorisはLRUキュー順序情報を定期的にディスクにダンプします。
- 再起動後ロード:ノードはダンプされたLRU情報を再ロードしてキュー状態を復元します。
- フルディスクスキャン:定期ダンプからの潜在的なメタデータ-ファイル不整合に対処するため、DorisはLRUロード後にフルディスクスキャンを実行して完全性を確保します。
- クエリ起動非同期ロード:スキャンに時間がかかるため、BEはプロセス中にクエリを提供できます。クエリがスキャンされていないデータにアクセスする場合、遅延を最小化するために早期ロードが発生します。
(5) スケーリング中のキャッシュ処理
スケーリング操作はクラスター管理で一般的です。Dorisはスケーリング中にファイルキャッシュを以下のように処理します:
- 水平スケールアウト:新しいBEへのタブレット移行中、ターゲットBEはソースBEからのメタデータを使用してキャッシュデータをダウンロードし、新しいノードでのキャッシュヒットを保証します。
- 水平スケールイン:スケールアウトと同様ですが、削減されたクラスターキャッシュ容量が実際のキャッシュサイズを下回る場合、標準機構に従って退避が発生します。
- 垂直スケールアウト:
- ディスク追加:Dorisはディスク間でリハッシュやバランシングを行わないため推奨されません。キャッシュディレクトリの変更は検索失敗を引き起こす可能性があります。必要な場合は、キャッシュをクリアして必要に応じてウォームアップしてください。
- ディスク容量増加:同一ディスク数での容量拡張の場合、
curl http://BE_IP:WEB_PORT/api/file_cache?op=reset&capacity=123456を使用してBEに通知します。
- 垂直スケールイン:
- ディスク領域削減:
reset操作も必要です。新しい容量がキャッシュサイズを下回る場合、標準機構に従って退避が発生します。
- ディスク領域削減:
- スケーリング後ウォームアップ注意事項:水平スケーリングはタブレットリバランシングを伴うため、効果的なウォームアップのために安定化を待ちます。
doris_fe_tablet_numメトリクスを監視してください。曲線が安定すると、ウォームアップが完了します。