MakingSenseofStreamProcessing / 3. Caching


How Database Are Used - 3.Caching

要約

アプリケーションで扱うキャッシュの方法とメリット・デメリットを説明しています。またキャッシュの扱い方と更新のプロセスについて扱っています。

詳細

ここで話しているのは、アプリケーションによって明示的に行われるキャッシュです。 (キャッシュは、オペレーティングシステムのページキャッシュやCPUのキャッシュなど、さまざまなレベルで自動的に行われますが、ここで言及しているものではありません)。

あなたが普及したウェブサイトを持っていて、ウェブリクエストごとにデータベースにヒットするにはコストがかかりすぎるか遅すぎると思いますので、memcachedやRedisなどを使用して実装されることが多いキャッシュ層を導入します。 多くの場合、このキャッシュはアプリケーションコードで管理されます。通常は図5-9のようになります。


Figure 5-9. A read-through cache managed in application code.


要求がアプリケーションに到着すると、まずキャッシュを検索して、必要なデータが既に存在するかどうかを確認します。 キャッシュルックアップは、通常、必要なデータを説明するキーによって表示されます。 データがキャッシュにある場合は、クライアントに直接返すことができます。

必要なデータがキャッシュにない場合は、キャッシュミスです。 基礎となるデータベースに行き、必要なデータを照会します。 途中で、アプリケーションはそのデータをキャッシュに書き込んで、それを必要とする次の要求のためにそこに格納します。 キャッシュに書き込むのは、アプリケーションが最初に参照したいと思っていたものです。 次に、アプリケーションはクライアントにデータを返します。 これは非常に一般的なパターンですが、いくつか大きな問題があります(図5-10)。


Figure 5-10. Problems with application-managed read-through caches.


キャッシュの無効化は、クリシェの点で困難な問題であると考えられています。基礎となるデータベースのデータが変更された場合、キャッシュ内のどのエントリが期限切れまたは更新されるかをどのように知っていますか?どのデータベース変更がどのキャッシュエントリに影響を与えるかを簡単なデータモデルでは扱いにくく、世代別キャッシュやロシアンドールキャッシングなどのアルゴリズムが使用されます。より複雑なデータ依存関係の場合、無効化アルゴリズムは複雑で、脆くなり、エラーを起こしやすくなります。一部のアプリケーションでは、有効期間(有効期限)のみを使用して、キャッシュから失効したデータを読み込むことがあることを受け入れることで、問題を解決しています。 別の問題は、このアーキテクチャが競合状態になりがちであることです。実際、これは第2章で示したデュアル書き込み問題の例です(図2-9)。複数のクライアントが同時に同じデータにアクセスすると、キャッシュがデータベースと矛盾する可能性があります。

3番目の問題はコールドスタートです。 memcachedサーバを再起動してキャッシュされたすべてのコンテンツを失った場合、突然リクエストがキャッシュミスになり、リクエストが急激に増加してデータベースが過負荷になり、あなたは苦痛の世界に入ります。新しいキャッシュを作成する場合は、システムの他の部分に過負荷をかけることなく、コンテンツをブートストラップする方法が必要です。 そこで、ここではコントラストがあります(図5-11)。一方では、データベースにセカンダリインデックスを作成することは非常にシンプルです.SQLの1行です。データベースは自動的に処理し、最新のものをすべて維持し、インデックスをトランザクション的に一貫したものにします。一方、アプリケーションレベルのキャッシュメンテナンスは、複雑な無効化ロジック、競合状態、および運用上の問題が完全に混乱します。


Figure 5-11. Databases hide the complexity of creating a secondary index behind a simple interface, but application-level cache maintenance is a complete mess.


それがなぜそのようにすべきでしょうか? セカンダリインデックスとキャッシュは基本的に異なるわけではありません。 先に述べたように、セカンダリインデックスは、読み取りクエリを高速化するために、同じデータを別の方法で構造化する、冗長なデータ構造にすぎません。 これについて考えると、キャッシュは、データをあるフォーム(データベースに格納されているフォーム)に取り込んで、読み込みを高速化するために別のフォームに変換した結果です。 つまり、キャッシュの内容はデータベースの内容から導出されます(図5-12)。これはインデックスに非常に似ています。


Figure 5-12. Similarly to an index, the contents of a cache are derived from the contents of the database.


セカンダリインデックスは、すべてのレコードから1つのフィールドを取り出し、それを辞書のキーとして使用することで作成されています(図5-7)。 キャッシュの場合、データに任意の関数を適用することができます(図5-12)。データベースからのデータは、キャッシュに入れる前にある種のビジネスロジックやレンダリングを行っている可能性があります。 異なるテーブルから複数のレコードを結合した結果。 しかし、最終的な結果は似ています。キャッシュを失った場合、元のデータベースから再構築できます。 従って、キャッシュの内容はデータベースから導出される。

リードスルーキャッシュでは、この変換はキャッシュミスが発生したときに実行されます。 しかし、キャッシュの構築と更新のプロセスをより体系的に、セカンダリインデックスに似ていると想像することもできます。 後でその考えに戻りましょう。

次に、データベースについての第4の考え方、すなわちマテリアライズド・ビューに移りましょう。


担当者のつぶやき

みんなの突っ込み