We’re sorry we missed you at re:Invent, but we can still meet!

キャッシュ戦略を実行するための6つの一般的なキャッシュ・デザイン・パターン

キャッシュは強力だが、キャッシュ・デザイン・パターンは万能ではない。

アレックス・デブリー
著者

Share

キャッシング戦略を実装する際に必要な3つの重要なキャッシングの選択がわかったところで、これらの選択から導かれる人気のあるキャッシング・デザイン・パターンをいくつかおさらいしましょう。それぞれについて、そのパターン、そのパターンが3つのキャッシュ選択のどれに従うか、そしてそのパターンをどのようなときに使いたいかを説明します。

1: ローカル・ブラウザ・キャッシュ

最初の、そしておそらく最も単純なキャッシング・デザイン・パターンは、ローカル・ブラウザ・キャッシングです。ブラウザからアクセスするウェブベースのアプリケーションを構築している場合、ローカルストレージを使用してユーザーのブラウザにキー値データを保存することができます。例えば、一度ユーザがあなたのサービスに認証されると、そのユーザのIDやサービスへのアクセスに使用されたプロファイルに関する情報を保存し、その後の閲覧時にアプリケーションの表示を高速化することができます。

ローカルブラウザのキャッシュは、ローカルで、脇役のキャッシュであり、読み込み時に書き込まれる可能性が高いです。

ローカルブラウザキャッシュの利点は、ローカルストレージAPIが最新のウェブブラウザに含まれているため、シンプルであることです。さらに、このデータをキャッシュするためにユーザーのマシン上のスペースを事実上貸し出しているため、事前にキャッシュをプロビジョニングしたり、スペースが足りなくなることを心配する必要はありません。

ローカル・ブラウザー・キャッシュの欠点は、特定の状況でしか使えないことです。ユーザーがブラウザを再利用する場合、特定の操作を簡単にスピードアップできます。しかし、キャッシュされたデータは、異なるデバイスを使用している時、あるいはデバイス上で異なるブラウザインスタンスを使用している時でさえ、ユーザーには適用されません。さらに、基礎となるデータが変更された場合、バックエンドのデータソースがローカル・ストレージ・キャッシュのアイテムをプロアクティブに無効にするメカニズムはありません。

2: ローカル・バックエンド・キャッシュ

ブラウザのエンドユーザークライアントでローカルキャッシュができるように、バックエンドアプリケーションのクライアントでもローカルキャッシュができます。ローカルバックエンドキャッシュデザインパターンでは、バックエンドサーバーインスタンスは他のシステムからのネットワークレスポンスや中間データをキャッシュすることができます。このデータは、プログラミング言語のキー・バリュー・マップのように、アプリケーション・プロセス内でメモリ内にキャッシュされることがよくあります。バックエンドインスタンスがそのデータにアクセスする必要がある場合、まずインメモリオブジェクトをチェックし、キャッシュされた値が存在しない場合はプライマリデータソースにフォールバックします。

ブラウザのローカル・キャッシュと同様、これはローカルで、読み込み時に書き込まれる可能性が高いキャッシュ戦略です。

この戦略の利点は、使いやすさとシンプルさにあります。頻繁にアクセスされ、比較的寿命の長いデータがある場合、追加のインフラを立ち上げて運用することなく、個々のサーバーインスタンスに素早くキャッシュすることができます。これは、設定データなど動きの遅いデータには効果的です。

ある意味、これはAWS Lambda内でMomento SimpleClientを再利用(または「キャッシュ」)して接続の再利用を可能にする方法と似ています。

このキャッシュ戦略の欠点は、リモート・キャッシング手法よりも効果が低いことです。各バックエンドインスタンスはそれぞれ独立したキャッシュを持つことになります。キャッシュするデータセットが幅広く、そのインスタンスで一度リクエストされたものだけをキャッシュする場合、キャッシュのヒット率はかなり低くなります。さらに、クラスタ・サイズ(そしておそらく全体的な負荷)が大きくなると、キャッシュ・ヒット率はさらに低くなります!これは、AWS Lambdaのような、インスタンスが定期的に生成・破棄されるハイパーエフェメラルなコンピュートでキャッシュする場合に特に厄介です。最後に、ローカルブラウザのキャッシュと同様に、基礎となるデータが変更された場合、バックエンドインスタンスで期限切れのデータを無効にするのは難しいかもしれません。

3: リード・アサイド・キャッシング

リード・アサイド・キャッシング(一般に「レイジー・ローディング」と呼ばれる)は、最も一般的なキャッシュ・デザイン・パターンです。この戦略では、アプリケーションはまずキャッシュから必要なデータを要求しようとします。データがそこにあれば、呼び出し元に返します。もしデータがなければ、プライマリー・データ・ソースにデータをリクエストします。そして、次のリクエストに備えてキャッシュにデータを保存し、呼び出し元にデータを返します。

これは、リモートの、読み取りベースの、脇役のキャッシング戦略です。

リード・アサイド・キャッシング戦略の利点は、キャッシュ・ヒット率の向上と、ほとんどの問題への汎用性にあります。ほとんどのアクセスパターンにおいて、一度アクセスされたデータ片は、その後すぐに再びアクセスされる可能性が高く、データの一部が読み込まれた後、一元化された場所にキャッシュすることで、サーバー群全体のキャッシュヒット率を向上させることができます。さらに、リード・アサイド・キャッシュ戦略は、ほぼすべての状況に適用できます。ネットワーク・レスポンス、中間計算の後、HTTPクライアントへの完全な集約レスポンスなどです。

ローカルキャッシュからリモートキャッシュに移行することで、ヒット率は上がりますが、運用の負担が増え、アプリケーションの複雑さも増します。管理すべきインフラが増え、システム全体の可用性への影響も考慮しなければなりません。プライマリ・データ・ソースにフォールバックするので可用性に影響はないと思うかもしれないが、多くの停止は、プライマリ・データ・ソースに持続不可能な負荷をかけることにつながる初期キャッシュ障害が原因です。

さらに、リード・アサイド・キャッシュは、データ の最初の読み取りに対してレイテンシ・コストを支払いあす。アプリケーションの読み取りがアプリケーション内のレコードに分散している場合、キャッシュがほぼ満杯になり、全体的にキャッシュヒット率が低くなる可能性があります。

ライトアサイド・キャッシング

次のキャッシング・デザイン・パターンは前と似ています。ライトアサイド・キャッシングでは、リードアサイド・キャッシングのように集中型のキャッシュを使用します。しかし、初めてアクセスした後にキャッシュにアイテムをロードするのではなく、データを書き込むときに積極的にキャッシュにデータをプッシュします。

これは、リモートで、書き込みベースの、脇役のキャッシング戦略です。

ライト・サイド・キャッシュ戦略の利点の多くは、リード・サイド・キャッシュ戦略に似ています。集中型キャッシュではキャッシュヒット率が高くなります。さらに、各エントリーの最初のミスがなくなるので、キャッシュ・ヒット率はさらに高くなるはずです。これにより、書き込み後すぐにアクセスされることがわかっているデータの待ち時間を短縮することができます。最後に、正しく実装されていれば、すべてのデータ更新が即座にキャッシュに反映されるため、データが古くなる可能性を減らすことができます。

ライト・アサイド戦略の欠点は、複雑さが増すことです。リード・アサイド・キャッシングは、単一のデータ・アクセス・パスの中でどのように実装されるかという点では簡単です。ライト・アサイド・キャッシングでは、キャッシュのキーと値のフォーマットを理解するために、読み取りパスと書き込みパスが連携する必要があります。さらに、読み取りと書き込みの両方のアクセスパターンを深く理解する必要があります。そのためには、入念な監査と、データの陳腐化を防ぐための絶え間ない警戒が必要となります。

5 & 6: リードスルーとライトスルー・キャッシング

最後の2つのキャッシュ・デザイン・パターンは、すべてのデータ・アクセスがキャッシュを直接経由するという点でユニークです。アプリケーションはキャッシュにリクエストを行い、リクエストされたデータを取得します。データがローカルで利用可能であれば、キャッシュはそれを返します。そうでない場合は、キャッシュ自身がプライマリ・データ・ソースからデータをフェッチし、データをキャッシュして、あなたに返します。

たとえば、下の図はライトスルー・キャッシュのフローを示しています。まず、アプリケーションに書き込み要求が来ます。アプリケーションはデータを直接キャッシュに書き込み、キャッシュはそれをメイン・データベースに永続化します。キャッシュが書き込みが永続化されたことをアプリケーションに返すと、アプリケーションはレスポンスを返します。

これは、リモート・インライン・キャッシュ戦略で、リード側でもライト側でも使用できます。

コンテンツ・デリバリー・ネットワーク(CDN)はリードスルー・キャッシュの一種です。

クライアントはコンテンツの一部に対してHTTPリクエストを行い、CDNは利用可能であればエッジロケーションからそれを提供し、そうでなければオリジンに戻ります。CDNがオリジンからコンテンツを取得した場合、その後のリクエストのためにエッジに保存します。VarnishNginxなど、HTTPベースのリードスルー・キャッシュもいくつかあります。

データベースベースのインラインキャッシュはもっと稀だが、存在します。DynamoDB Accelerator (DAX)は、DynamoDBのリードスルーキャッシュです。DAXに対してDynamoDBテーブルと同じ操作を行うことができ、DAXインスタンスは必要に応じてDynamoDBテーブルへの読み書きを転送します。

インライン・キャッシュの利点は、クライアントの観点からはそのシンプルさにあります。‍

キャッシュ・キーを管理したり、キャッシュ・ミスを処理するために多段階のロジックを実装したりする必要がありません。インライン・キャッシュがこれを処理します。さらに、インライン・キャッシュはリモート・キャッシュであるため、脇のキャッシュに見られるような、より高いキャッシュ・ヒット率の恩恵を受けることができます。

インライン・キャッシュにはデメリットもあります。第一に、データ・ソースのインライン・キャッシュは見つけにくいか、存在しない可能性があります。インライン・キャッシュの作成者は、基礎となるデータ・ソースへのフォールバックを処理するロジックを実装する必要があります。実装によっては、インライン・キャッシュを使用する場合と使用しない場合のアプリケーションの動作に矛盾が生じる可能性があります。さらに、インラインキャッシュを使用すると、アプリケーションに重要なインフラストラクチャが追加され、アサイドキャッシュよりも可用性に影響する可能性があります。

結論

正しいキャッシング・デザイン・パターンを使えば成功に導くことができるが、間違ったものを使えば苦境に立たされることになります。この内訳についてのあなたの考えをツイートしてください。役に立ちましたか?私が見逃したパターンや、もっと詳しく説明できたパターンはありますか?

Momento Cacheは、リモートで集中管理されたリード・アサイド・キャッシュが必要な場合に最適です。キャッシュ戦略が異なる場合でも、Momentoの専門家に相談する価値があります。

データベースの運用に頭を悩ませることなく、データベースを強化する方法について詳しく知りたい方は、Momentoにご連絡ください。今すぐお問い合わせください!

Share