バックエンド開発者であれば、Web アプリケーションを高速化する必要があるときはいつでもキャッシングが頼りになるソリューションです。ただし、Web アプリケーションに適したキャッシング戦略を決定する際に、キャッシングに関して見落としがちなことがたくさんあります。したがって、この記事では、利用可能なさまざまなキャッシング戦略と、ユースケースに適したものを選択する方法について説明します.
簡単に言えば、キャッシングは、頻繁にアクセスされるデータを一時メモリまたはスペースに保存して、すぐに利用できるようにし、アプリケーション、サーバー、またはデータベースの作業負荷を軽減するバッファリング手法です。ユースケースに応じて、Web アプリケーションのさまざまなレベルで実装できます。
キャッシュは、次のような Web アプリケーションのさまざまなレベルで発生します。
CDN は、静的アセット (画像、ビデオ、Web ページなど) を地理的に分散したサーバーにキャッシュするために使用され、キャッシュを使用してエンド ユーザーにコンテンツをより高速に送信できるようにします。
CDN を食料品店のチェーンと考えてください。買い手は、食料が栽培されている畑まで何百キロも移動する代わりに、移動が必要ですが、かなり近い地元の食料品店に行きます。食料品店は遠く離れた農場から食料品を仕入れているため、食料品の買い物は数日ではなく数分で完了します。同様に、CDN はインターネット上に表示されるコンテンツを「ストック」して、Web ページの読み込みを大幅に高速化します。
ユーザーが CDN を使用して Web サイトからコンテンツを要求すると、CDN はオリジン サーバーからコンテンツを取得し、今後の要求のためにコンテンツのコピーを保持します。キャッシュされたコンテンツは、ユーザーがアクセスし続ける限り、CDN キャッシュに保持されます。
データベース キャッシングとは、読み取りと書き込みを最適化するために任意のデータベースで使用されるネイティブのスマート キャッシング アルゴリズムを指します。この場合、キャッシュは、データベース、アプリケーション、またはスタンドアロン レイヤーを含む複数の領域に配置できます。
データベース キャッシングは、NoSQL データベースだけでなく、SQL サーバー (MySQL や MariaDB など) などのリレーショナル データベースを含む、あらゆる種類のデータ ストアで使用できます。また、AWS や Microsoft Azure などの多くのデータ プラットフォームでもうまく機能します。
ブラウザーまたはクライアントは、キャッシュの有効期限ヘッダーに基づいて静的アセットを保存します。 HTTP キャッシュ ヘッダーは、ブラウザーが要求された Web コンテンツに対する後続のキャッシュ応答を実行できる期間を指定します。また、ブラウザーは、不要なデータ呼び出しを避けるために、GET 要求の応答をキャッシュすることができます。
サーバー キャッシングは、データがサーバー アプリケーションにキャッシュされる最も一般的に知られており、使用されているキャッシング メカニズムです。ここでは、ビジネス ニーズに大きく依存します。同時ユーザーが少ないアプリケーション向けに高度に最適化されています。
サーバー側の Web キャッシングでは、多くの場合、Web プロキシを使用して、その前にある Web サーバーからの Web 応答を保持し、負荷と待ち時間を大幅に削減します。これらのキャッシュは、サイト管理者によって実装され、ブラウザとオリジン サーバーの間の中間エージェントとして機能します。
サーバー側キャッシングのもう 1 つの形式は、Memcached や Redis などのキー値ストアを利用することです。対照的に、特定の HTTP 要求に対する HTTP 応答をキャッシュするだけのリバース プロキシでは、アプリケーション開発者が必要とする Web コンテンツはすべて、キー/値オブジェクト ストレージを使用してキャッシュできます。多くの場合、Web コンテンツは、インメモリ データ ストレージを悪用するアプリケーション コードまたはアプリケーション フレームワークを使用してフェッチされます。
オンライン キャッシングにキー/バリュー ストアを採用するもう 1 つの利点は、それらが Web セッションやその他のキャッシュされた素材を保存するために頻繁に使用されることです。これにより、さまざまなアプリケーション状況に対応する統合ソリューションが提供されます。
以下に示すように、キャッシュにはいくつかの利点があります。
前に説明したように、キャッシュは、頻繁にアクセスされ、通常は一時的なデータのサブセットを格納する高速データ ストレージ レイヤーであるため、将来の要求は、元のストレージの場所にアクセスするよりも高速に処理されます。したがって、キャッシングにより、以前にアクセスまたは計算されたデータを効率的に再利用できます。したがって、データの読み取り/書き込み操作が大幅に削減され、アプリケーションの全体的なパフォーマンスの向上に役立ちます。
1 つのキャッシュ インスタンスで 1 秒あたり数十万回の入出力操作を実行できるため、必要なデータベース インスタンスの数を減らすことで総コストを削減できます。したがって、ストレージの料金がスループットごとであれば、コストを大幅に節約できます。
キャッシュは、バックエンド データベースからインメモリ キャッシュ レイヤーに読み取り負荷の特定の部分をリダイレクトすることで、バックエンド サーバーの負荷を効果的に削減し、パフォーマンスの低下を防ぐことができます。トラフィックの過負荷やスパイク時にシステムがクラッシュするのを防ぐことができます。
最新のアプリケーションに共通する課題は、アプリケーションの使用量の急増に対処することです。たとえば、世界規模の技術イベント、クリケットの試合、選挙の日、または e コマース Web サイトでのお祝いのセールなどでソーシャル メディア アプリケーションが急増する場合があります。ユーザーエクスペリエンスも予測不可能です。ただし、高スループットのメモリ内キャッシュを使用することで、この問題を大幅に軽減できます。
多くのアプリケーションでは、有名人のプロフィールや人気のある製品など、データの小さなサブセットが残りの部分よりも頻繁に取得される可能性があります。これにより、データベースにホットスポットが発生し、最も頻繁に使用されるデータのスループット要件に基づいて、データベース リソースのオーバープロビジョニングが必要になる場合があります。共通キーをメモリに保存すると、オーバープロビジョニングの必要性が減り、最も頻繁にアクセスされるデータに対して高速で予測可能なパフォーマンスが提供されます。
インメモリ システムは、待機時間を短縮するだけでなく、同様のディスク ベースのデータベースよりもはるかに高い要求率を提供します。単一の分散型サイド キャッシュ マシンは、1 秒あたり数十万の要求に対応できます。
キャッシングの利点について説明したので、実際のユース ケースを使用してキャッシング戦略に飛び込みましょう。この記事では、主にサーバー側のキャッシュ戦略に焦点を当てます。
このキャッシュ戦略では、キャッシュは論理的に脇に置かれ、アプリケーションはデータベースまたはキャッシュと直接通信して、要求された情報が存在するかどうかを確認します。最初に、アプリケーションはキャッシュをチェックし、情報が見つかった場合はデータを読み取って返します。これはキャッシュ ヒットと呼ばれ、情報が見つからない場合はキャッシュ ミスと呼ばれます。アプリケーションはデータベースにクエリを実行して情報を読み取り、要求されたデータをクライアントに返します。また、将来の使用のためにキャッシュに保存します。
読み取りが多いユースケースでは本質的に有益です。したがって、キャッシュ サーバーがダウンしている場合、システムはデータベースと直接通信することによって適切に動作しますが、突然発生する可能性があるピーク負荷またはスパイクの場合には、長期的または信頼できるソリューションではありません。
最も一般的な書き込み戦略は、データベースに直接書き込むことですが、頻繁に書き込むとデータの不整合が発生する可能性があります。この状況に対処するために、開発者はしばしばTTL (Time to Live)を使用してキャッシュを使用し、有効期限が切れるまでサービスを継続します。
TTL を使用する場合と使用しない場合のキャッシュの概要と、それらを使用するタイミングを次に示します。
TTL を使用したキャッシュは、データが頻繁に更新される場合に最もよく使用されるキャッシュです。このような場合、定期的にキャッシュを失効させたいので、時間制限のあるキャッシュを使用すると、時間間隔が経過するとキャッシュが自動的に削除されます。
たとえば、サーバー セッションやスポーツのスコアカードなどです。
TTL のないキャッシュは、コースを提供する Web サイトのコンテンツなど、頻繁に更新する必要のないキャッシュのニーズに使用されます。この場合、コンテンツは頻繁に更新または公開されないため、時間制限なしでキャッシュする方がはるかに簡単です。
名前が示すように、この戦略では、新しい情報はメイン メモリ/データベースの前に最初にキャッシュに書き込まれます。この場合、キャッシュは論理的にアプリケーションとデータベースの間にあります。したがって、クライアントが何らかの情報を要求した場合、キャッシュには既に情報が含まれているため、アプリケーションは情報の可用性をキャッシュで確認する必要がなく、キャッシュから直接取得され、クライアントに提供されます。
ただし、書き込み操作のレイテンシが増加します。しかし、リードスルー キャッシュと呼ばれる別のキャッシュ戦略と組み合わせると、データの一貫性を確保できます。
このキャッシュ戦略では、キャッシュ ミス (キャッシュ内にデータが見つからない) が発生するたびに、欠落しているデータがデータベースから取り込まれ、クライアントに返されるように、キャッシュがデータベースと一致します。
ご想像のとおり、これは、同じ情報セットが何度も要求されるような負荷の高いアプリケーションに最適です。たとえば、ニュース Web サイトは、同じ記事を 1 日何度も配信します。
この戦略の欠点は、データが初めて要求された場合、常にキャッシュ ミスであるため、通常の要求よりも遅くなることです。
このキャッシュ戦略では、書き込み操作があるたびに、アプリケーションは情報をキャッシュに書き込みます。キャッシュは変更をすぐに認識し、少し遅れてデータをデータベースに書き戻します。これは、後書きキャッシュ戦略とも呼ばれます。
これは、アプリケーションの書き込みパフォーマンスを向上させるための書き込み操作が多いアプリケーションに適したキャッシュ戦略です。また、インスタンスで発生する可能性がある中程度のデータベースのダウンタイムと障害に対応するのにも役立ちます。
また、リードスルー キャッシュと組み合わせるとうまく機能します。さらに、バッチ処理がサポートされている場合、データベースへの書き込みワークロードをさらに削減できます。ただし、欠点は、キャッシュに障害が発生した場合、データが永久に失われる可能性があることです。ほとんどのリレーショナル データベースでは、ライトバック キャッシュ メカニズムがデフォルトで有効になっています。
この場合、データはデータベースに直接書き込まれ、読み取られたデータのみがキャッシュに格納されます。
これはリードスルー キャッシュと組み合わせることができ、データが 1 回書き込まれ、数回しか読み取られない場合に適しています。たとえば、リアルタイムのログやチャットが必要な場合です。
この記事では、キャッシングとは何か、アプリケーションでのキャッシングのさまざまなレベル、およびキャッシングが必要な理由について説明しました。次に、サーバー側キャッシングのさまざまなキャッシング戦略についても説明しました。ただし、これらのキャッシング戦略のいずれかが実際のユースケースを満たす必要はありませんが、最良の結果を得るためにこれらの戦略を組み合わせることを常にお勧めします。
これに慣れていない開発者にとっては、実用的な意味で概念をより完全に理解し、特定のユースケースに最適なソリューションを考え出すために、試行錯誤が必要になる場合があります。
この記事は以上です。お役に立てば幸いです。あなたの考えを教えてください。ここで私とつながることができます:
読み続けます!