キャッシュを理解するのにコンピューターサイエンスの学位は必要ありませんし、非常に基本的な概念とさえ思うかもしれません。
本記事では、私がソフトウェア エンジニアとして、高性能で複雑な分散システムを構築してきた 10 年以上の経験の集大成をもとに解説します。
キャッシュとは?
キャッシュとは、データ(ファイル、テーブル、その他のデータ構造)をキャッシュまたは一時的な記憶場所に保存するプロセスのことです。
通常はアプリケーションのパフォーマンスを向上させ、データ・アクセスを高速化するために行われます。
そして、キャッシュ・データはメモリ、ディスク、キャッシュ・サーバなどに保存されます。
キャッシュの特徴
キャッシュ・プロセスは、以前に取得または計算されたデータを再利用する効率的な方法を提供し、より低速な基礎となるストレージ層へのアクセスの必要性を減らすために使用されます。
キャッシュのメリット
適切なキャッシュは、データベースやサーバーのリソースの消費を減らします。
高速なストレージは通常、サイズが制限され、コストが高く、揮発性が高いため、すべてのデータを保存するのは現実的ではありません。
キャッシュのデメリット
一方、キャッシュには、キャッシュデータが古くなることによるデータの不整合や、データベースやアプリケーション自体の管理・メンテナンスのレイヤーが増えることなどがあります。
キャッシュはハードウェアで広く使用されています。
たとえば、現在使用しているデバイスの CPU には、2 ~ 4 つのキャッシュ レベルが組み込まれている可能性があります。
ただし、ソフトウェア エンジニアリングでは、キャッシュとは、低速で永続的なデータベースの前に揮発性のインメモリデータストアを配置することを指すことがよくあります。
データベースとキャッシュを組み合わせる
多くのデータベースには、内部キャッシュ層が装備されています。
例えば、MongoDB、CouchBase、ScyllaDBなどがその一例です。
ただし、パフォーマンスを向上させるために、 RDBMS、 Cassandra、DynamoDBなど、パフォーマンスが遅い傾向にあるデータベースの前にMemcached、 Redis、ElastiCacheなどのキャッシュ テクノロジーを配置するのが一般的です。
キャッシュ層の統合によりデータベースアクセスが遅いアプリケーションを高速化できるのか
残念ながらできません。
本題に入る前に、速度とは何を意味するのかを明確にしましょう。
コンピューターシステムのコンテキストでは、リクエストがシステムに送信されて応答が即座に受信されると、そのシステムは高速であると考えられます。
したがって、速度は本質的に応答時間に関連しています。
しかし、コンピューターシステムは複雑です。
負荷が高い場合、システムの応答時間は、ワークロードが最小限の場合のパフォーマンスと大きく異なる可能性があります。
リクエストの処理中に発生する良いシナリオと悪いシナリオの両方を包括的に考慮して、レイテンシのパーセンタイルを使用して速度を評価します。
では、レイテンシーのパーセンタイルとは何でしょうか?
レイテンシのパーセンタイルを理解する
長期間にわたってシステムの応答時間を記録するプロセスについて考えてみましょう。
このデータを収集した後、応答時間を最も遅いものから最も速いものへと昇順に並べます。
この順序付けられたシーケンスの中央の値は、システムのレイテンシの 50 パーセンタイル、つまり P50 です。
P50 が T 秒の場合、システムの応答の半分が T 秒より遅いことを示します。
リストの 9/10 番目の位置にある値 (P90 と表記) は、要求の 90% が完了した時間を示します。
同様に、P95、P99、P99.9 などの他のパーセンタイルを定義できます。
これらはそれぞれ、要求のそれぞれの割合が満たされるまでの時間を表します。
最新のデータベースなどの分散システムのレイテンシをプロットすると、結果として得られるグラフはホッケースティックのプロファイルを反映することがよくあります。
さまざまなテクノロジーのレイテンシーグラフの詳細は異なる場合がありますが、一般的には以下に示すパターンに準拠しています。
P10 と P90 の応答時間の差は、P99 から P99.9 への急激な増加に比べて大幅に小さいことに注目してください。
この差異は、分散システムの予測不可能な動作に根ざしています。
説明のために、2 つの有害事象が発生しやすいシステムを考えてみましょう。
- ガベージコレクション:
- 発生確率:1%
- 平均持続時間: 2 ミリ秒
- ランダムなネットワーク パケット損失:
- 発生確率:0.1%
- リトライ期間:2秒
これらの条件を考慮すると、ガベージ コレクションイベントが 1% の確率で発生すると、P99 パーセンタイル以上で応答時間が 2 ミリ秒遅延します。
同様に、P99.9 パーセンタイルでは、ネットワーク パケット損失が発生する確率が 0.1% であるため、応答が 2 秒遅れる可能性があります。
さらに、パケット損失に続いてガベージ コレクションが発生したり、2 回連続してパケット損失が発生したりするなど、複数の有害なイベントが発生する確率が累積すると、パーセンタイルが高くなりレイテンシーの差がさらに開きます。
このシナリオは、まれなイベントが遅延に大きな影響を与える可能性がある分散システムにおけるパフォーマンス管理の複雑さを強調しています。
ここで、議論の主要なトピックであるキャッシュに注意を戻しましょう。
キャッシュヒット率の重要性
キャッシュのタイプやデータの削除に使用されるアルゴリズムに関係なく、必要なデータが常にキャッシュ内にあるとは限りません。
キャッシュにアクセスして必要なデータを見つけられる可能性を「キャッシュヒット率」といいます。
次のグラフの赤い線で示されているように、ストレージシステムにキャッシュを導入すると、全体的な遅延プロファイルが変更されます。
赤い線は 3 つの異なる領域に分割できます。
- 緑:この領域は、キャッシュによって正常に処理されたリクエストを表し、キャッシュ ヒット率によってこの領域のサイズが決まります。
- 青:キャッシュ内にリクエストが見つからなかった場合、システムは標準の動作に戻り、キャッシュの実装前と同様の応答時間になります。
- オレンジ:キャッシュ層を導入すると、コンポーネントが増えるため、まれに有害事象が発生する可能性が高まる可能性があり、より高いパーセンタイルでレイテンシが増加する可能性があります。
キャッシュに期待できること
データベースが必要な速度を満たせないためにアプリケーションのパフォーマンスが低下するシナリオを考えてみましょう。
複雑なアプリケーションでは、高レベルのリクエストの処理に複数のサービスとコンポーネントが関与することが多く、その一部はデータベースにクエリを実行する必要があります。
キャッシュ ヒット率が P で、同時データベース アクセス要求が n 個ある場合、n 個の要求すべてがキャッシュから直接処理される可能性は P^n です。
たとえば、キャッシュ ヒットの確率が 50% で、並列リクエストが 5 つ (n=5) ある場合、これらすべてのリクエストがキャッシュ ヒットになる確率は 0.5^5 で、これは 0.031 または 3.1% に相当します。
リクエストは、そのコンポーネントのクエリがすべて応答された後にのみ完全に処理されるため、96.9% の場合、リクエストはキャッシュの存在による恩恵を受けないことになります。
これは、遅いデータベースにアクセスする必要がある少なくとも 1 つのクエリが完了するまで待機する必要があるためです。
実際の目標は、P99 のようなパーセンタイルでサービスの応答時間を改善することです。
キャッシュを導入して 5 つのオペレーションを持つタスクの P99 レイテンシを強化するには、ヒット率がなんと99.8% (0.998^5 = 0.99) でなければなりません。
データの一部がまったくアクセスされない限り、夢のような 99.8% のキャッシュ ヒット率に達すると、基本的にデータベース全体がキャッシュに移動されることになります。
したがって、データベース ベンダーが「ワーキング セットがメモリに収まる」ように十分なメモリを用意するようにアドバイスするときは、メモリ内にディスク領域のクローンを作成した方がよいと暗にほのめかしているのです。次
回、彼らがその知恵を何気なく漏らしたときは、そのことを念頭に置いてください。
キャッシュとは?まとめ
本記事では、キャッシュの基本知識とキャッシュに関する一般的な誤解、つまりデータベースの前にキャッシュ (内部、外部、または統合) を配置するとアプリケーションのパフォーマンスが向上するという概念について解説しました。
単純にキャッシュを追加しても、ビジネスに意味のある形で利益をもたらすレベルまで応答時間は改善されないため、この考えは誤った方向に導かれることがよくあります。
ただし、まだすべてのキャッシュを削除しないでください。キャッシュは、戦略的に使用するとアプリケーションのパフォーマンスを向上できる貴重なツールの「1 つ」です。