varbitチャンクを使用する(しない)場合

2016年5月8日筆者: Björn “Beorn” Rabenstein

Prometheusサーバーの埋め込み時系列データベース(TSDB)は、各時系列の生サンプルデータを、サイズが1024バイトで一定のチャンクに整理します。生サンプルデータに加えて、チャンクにはいくつかのメタデータが含まれており、これによりチャンクごとに異なるエンコーディングを選択できます。最も基本的な区別はエンコーディングバージョンです。新しく作成されるチャンクのバージョンは、コマンドラインフラグ-storage.local.chunk-encoding-versionで選択します。これまでは、サポートされているバージョンは2つだけでした。0は元のデルタエンコーディング、1は改善されたダブルデルタエンコーディングです。リリース0.18.0で、バージョン2が追加されました。これはダブルデルタエンコーディングの別のバリエーションです。サンプルごとに可変ビット幅をチャンク内に使用するため、これをvarbitエンコーディングと呼びます。バージョン1はほとんどすべての点でバージョン0よりも優れていますが、バージョン1と2の間には実際のトレードオフがあります。このブログ投稿は、その決定に役立ちます。バージョン1はデフォルトのエンコーディングのままなので、この記事を読んだ後でバージョン2を試したい場合は、コマンドラインフラグで明示的に選択する必要があります。切り替えに害はありませんが、作成済みのチャンクは作成時にエンコーディングバージョンが変更されないことに注意してください。ただし、これらのチャンクは設定された保持期間に従って徐々に廃止され、コマンドラインフラグで指定されたエンコーディングを持つチャンクに置き換えられます。

varbitエンコーディングとは?

最初から、新しいエンコーディングを簡単に追加できるようにチャンク化されたサンプルストレージを設計しました。FacebookがインメモリTSDB Gorillaに関する論文を発表したとき、独立して開発されたGorillaとPrometheusのアプローチの間には多くの類似点があり、興味をそそられました。しかし、多くの根本的な違いもあり、GorillaからPrometheusを改善するためのインスピレーションを得られるかどうかを検討しました。

前方に無料の週末という稀な機会に、試してみることにしました。コーディングの spree で、後に(かなりのテストとデバッグの後)varbit エンコーディングとなるものを実装しました。

将来のブログ記事で、エンコーディングの技術的な詳細を説明します。今のところ、新しいvarbitエンコーディングと従来のダブルデルタエンコーディングのどちらを選択するかについて、いくつかの特徴を知っておくだけで十分です。(以降、後者を単に「ダブルデルタエンコーディング」と呼びますが、varbitエンコーディングもダブルデルタを使用していることに注意してください。ただし、異なる方法で。)

varbitエンコーディングの利点は何ですか?

要するに、それははるかに優れた圧縮率を提供します。ダブルデルタエンコーディングは実世界のデータセットでサンプルあたり約3.3バイトを必要としますが、SoundCloudの典型的な大規模本番サーバーでは、varbitエンコーディングはサンプルあたり1.28バイトまで削減されました。これは、スペース効率がほぼ3倍です(Gorillaで報告されているサンプルあたり1.37バイトよりもわずかに優れていますが、SoundCloudの典型的なデータセットはFacebookの典型的なデータセットとは異なる可能性があるため、これは控えめに考えてください)。

その影響を考えてみてください。RAMあたりのサンプル数が3倍、ディスクあたりのサンプル数が3倍、ディスクI/Oが3分の1、そしてディスクI/Oは現在、取り込み速度のボトルネックであるため、取り込みも3倍速くなります。実際、最近報告された毎秒80万サンプルの新しい取り込み記録は、varbitチャンクでのみ可能でした。もちろん、SSDも必要です。回転ディスクでは、ボトルネックははるかに早く到達するため、3倍の増加はさらに重要になります。

これらすべては、あまりにも良すぎるように聞こえます…

では、どこに落とし穴があるのでしょうか?

まず、varbitエンコーディングはより複雑です。そのため、値をエンコードおよびデコードする計算コストはいくらか増加し、サンプルデータを書き込んだり読み取ったりするすべてのものに根本的に影響します。幸いなことに、それは通常、操作の総コストのごく一部しか寄与しないものの、比例的な増加にすぎません。

varbitエンコーディングのもう1つの特性は、おそらくはるかに重要です。varbitチャンク内のサンプルはシーケンシャルにしかアクセスできませんが、ダブルデルタエンコードされたチャンク内のサンプルはインデックスでランダムにアクセスできます。Prometheusでの書き込みは追記専用であるため、異なるアクセスパターンはサンプルデータの読み取りにのみ影響します。実際の影響は、元のPromQLクエリの性質に大きく依存します。

範囲セレクターを評価するときや、スクレイピング頻度に近い解像度でダッシュボードをレンダリングするときに発生する、時間間隔内のすべてのサンプルを取得することは、比較的無害なケースです。Prometheusストレージエンジンは、間隔の開始点を見つける必要があります。ダブルデルタチャンクではバイナリサーチを実行できますが、varbitチャンクではシーケンシャルにスキャンする必要があります。ただし、開始点が見つかると、間隔内の残りのすべてのサンプルは anyway シーケンシャルにデコードする必要があり、varbitエンコーディングではわずかにコストが高くなるだけです。

チャンクから少数の非隣接サンプルを取得する場合、またはインスタントクエリと呼ばれる単一サンプルを単純に取得する場合、トレードオフは異なります。潜在的に、ストレージエンジンは、返される少数のサンプルを見つけるために多くのサンプルを反復処理する必要がある場合があります。幸いなことに、インスタントクエリの最も一般的なソースは、各関与する時系列の最新サンプルを参照するルール評価です。完全に偶然ではありませんが、最近、時系列の最新サンプルの取得を改善しました。本質的に、時系列に追加された最後のサンプルがキャッシュされるようになりました。最新サンプルのみを必要とするクエリは、チャンクレイヤーにヒットすることさえなくなり、その場合、チャンクエンコーディングは無関係になります。

インスタントクエリが過去のサンプルを参照しているためチャンクレイヤーにヒットする必要がある場合でも、ほとんどの場合、クエリの他の部分(インデックスルックアップなど)が総クエリ時間を支配するでしょう。しかし、varbitチャンクで必要なシーケンシャルアクセスパターンが非常に重要になり始める実際のクエリも存在します。

varbitチャンクにとって最悪のクエリは何ですか?

varbitチャンクの最悪のケースは、非常に長い時系列のチャンクの中間からちょうど1つのサンプルが必要な場合です。残念ながら、それには実際のユースケースがあります。時系列が適切に圧縮され、各チャンクが約8時間持続すると仮定しましょう。これは1日あたり約3チャンク、または1か月あたり約100チャンクです。問題の時系列を解像度100データポイントで過去1か月間表示するダッシュボードがあるとしましょう。ダッシュボードは、100個の異なるチャンクから1つのサンプルを取得するクエリを実行します。それでも、チャンクエンコーディング間の違いは、クエリ実行時間の他の部分によって支配されるでしょう。状況によっては、クエリはダブルデルタエンコーディングで50ミリ秒、varbitエンコーディングで100ミリ秒かかるかもしれません。

ただし、ダッシュボードクエリが単一の時系列だけでなく、数千の時系列にわたる集計に触れる場合、アクセスする必要のあるチャンクの数はそれに応じて乗算され、シーケンシャルスキャンのオーバーヘッドが支配的になります。(そのようなクエリは非難されており、頻繁に使用されるクエリの場合はレコーディングルールを使用することを推奨しています。ただし、ダブルデルタエンコーディングでは、クエリ時間はまだ許容範囲内であった可能性があります。たとえば、約1秒です。varbitエンコーディングに切り替えた後、同じクエリは数十秒かかる可能性があり、これは明らかにダッシュボードに望ましいものではありません。

経験則は何ですか?

できるだけ簡単に言うと、ディスク容量やディスクI/Oに制限がない場合は、心配しないで、古典的なダブルデルタエンコーディングのデフォルトのままにしてください。

ただし、より長い保持期間が必要な場合や、現在ディスクI/Oでボトルネックになっている場合は、新しいvarbitエンコーディングを試してみてください。-storage.local.chunk-encoding-version=2でPrometheusサーバーを起動し、varbitエンコーディングを持つ新しいチャンクが十分に蓄積されるまでしばらく待ってから効果を確認してください。クエリが許容できないほど遅くなっている場合、レコーディングルールを使用して速度を改善できるかどうかを確認してください。ほとんどの場合、それらのクエリは、古いダブルデルタエンコーディングでも大幅に改善されるでしょう。

varbitエンコーディングの仕組みについて詳しく知りたい場合は、近日公開予定の別のブログ記事をお楽しみに。