キャッシュは、アプリケーションのパフォーマンスを向上させるための最も効果的な手法です。 キャッシュを適切に設計すると、データベースの負荷が 90% 削減され、応答時間が 200 ミリ秒から 2 ミリ秒に短縮され、毎月のインフラストラクチャ コストが数千ドル節約されます。しかし、キャッシュはソフトウェア エンジニアリングの分野で最も誤解されている分野の 1 つでもあります。無効化バグにより古いデータが作成され、キャッシュ スタンピードによりサーバーがダウンし、適切に選択されていない TTL はメモリを浪費したり、古いコンテンツを提供したりします。
パフォーマンスとスケーラビリティシリーズの一部
完全ガイドを読むキャッシュは、アプリケーションのパフォーマンスを向上させるための最も効果的な手法です。 キャッシュを適切に設計すると、データベースの負荷が 90% 削減され、応答時間が 200 ミリ秒から 2 ミリ秒に短縮され、毎月のインフラストラクチャ コストが数千ドル節約されます。しかし、キャッシュはソフトウェア エンジニアリングの分野で最も誤解されている分野の 1 つでもあります。無効化バグにより古いデータが作成され、キャッシュ スタンピードによりサーバーがダウンし、適切に選択されていない TTL はメモリを浪費したり、古いコンテンツを提供したりします。
重要なポイント
- レイヤー内のキャッシュの設計: ブラウザーから CDN、アプリケーション (Redis)、データベース クエリ キャッシュ -- 各レイヤーは異なるデータ特性を処理します
- Redis キャッシュアサイド パターンが最も安全なデフォルトです: キャッシュから読み取り、データベースにフォールバックし、ミス時にキャッシュにデータを追加します
- HTTP キャッシュ ヘッダー (Cache-Control、ETag、Vary) により、不要なリクエストが完全に排除されます -- 最速のリクエストはサーバーに到達しないリクエストです
- キャッシュの無効化はキャッシュよりも困難 -- 主要な戦略として TTL ベースの有効期限を使用し、重要なデータの鮮度を保つためにイベント ドリブンの無効化を使用します。
キャッシュ階層
効果的なキャッシュはレイヤーで機能し、各レイヤーはさまざまなレイテンシー、容量、鮮度の要件に合わせて最適化されます。
| レイヤー | レイテンシ | 容量 | 最適な用途 | 無効化 |
|---|---|---|---|---|
| ブラウザキャッシュ | 0ms (ローカル) | デバイスによる制限 | 静的資産、ユーザー固有のデータ | キャッシュ制御ヘッダー |
| CDN エッジ キャッシュ | 5~50ミリ秒 | エッジ ノード全体でテラバイト | 静的アセット、パブリック API 応答 | パージ API、TTL |
| アプリケーションキャッシュ (Redis) | 1~5ミリ秒 | ギガバイト (RAM 制限あり) | セッション データ、計算結果、レート制限 | TTL + イベントドリブン |
| データベースクエリキャッシュ | 10~50ミリ秒 | 設定可能 | 同一のクエリが繰り返される | テーブル書き込み時の自動 |
レイヤ 1: ブラウザ キャッシュ
ブラウザ キャッシュはネットワーク リクエストを完全に排除するため、最も高速かつ低コストのキャッシュです。 HTTP Cache-Control ヘッダーは、ブラウザーのキャッシュ動作を制御します。
コンテンツがハッシュ化されたファイル名を持つ静的アセット (Next.js ビルド出力など) の場合は、Cache-Control: public, max-age=31536000, immutable を設定します。ファイル名のコンテンツ ハッシュにより、変更されたコンテンツが新しい URL を取得することが保証されるため、コンテンツが古いことを心配せずに積極的にキャッシュできます。
HTML ページと API 応答の場合は、再検証で短い TTL を使用します: Cache-Control: public, max-age=60, stale-while-revalidate=300。これにより、キャッシュされたコンテンツが 60 秒間提供され、その後バックグラウンドで再検証され、最長 5 分間古いコンテンツが提供され続けます。
レイヤ 2: CDN エッジ キャッシュ
CDN は、グローバルに分散されたエッジ サーバーにコンテンツをキャッシュし、各ユーザーに最も近い場所からコンテンツを提供することで待ち時間を短縮します。グローバル ユーザー ベースの場合、CDN キャッシュにより平均遅延が 200 ~ 500 ミリ秒 (オリジン サーバーの往復) から 10 ~ 50 ミリ秒 (ニアレスト エッジ) に短縮されます。
CDN にキャッシュするもの:
- すべての静的アセット (JavaScript、CSS、画像、フォント)
- 公開マーケティング ページ (コンテンツの鮮度を保つために短い TTL を使用)
- 製品カタログ ページ (電子商取引の場合は 5 ~ 15 分の TTL)
- 公開データ (製品リスト、ブログ コンテンツ) に対する API 応答
CDN にキャッシュしてはいけないもの:
- 認証された API 応答 (ユーザー固有のデータ)
- ショッピングカートとチェックアウトページ
- 管理者パネルのページ
- Webhook エンドポイント
- Set-Cookie ヘッダーを含むすべての応答
レイヤ 3: アプリケーション キャッシュ (Redis)
Redis は、キャッシュされたデータへのマイクロ秒の遅延アクセスを提供するため、計算コストが高いデータや頻繁にアクセスされるデータに最適です。 CDN キャッシュとは異なり、Redis はアプリケーションがアクセスを制御するため、認証されたユーザー固有のデータをキャッシュできます。
レイヤ 4: データベース クエリ キャッシュ
PostgreSQL は、頻繁にアクセスされるテーブル ページとインデックス ページをメモリ内にキャッシュするバッファ キャッシュ (shared_buffers) を維持します。クエリごとに直接制御することはできませんが、適切な構成により、ホット データがメモリ内に確実に保持されます。レポート クエリの場合は、高価な集計を事前計算するマテリアライズド ビューを検討してください。
Redis キャッシュ パターン
Redis は、Web アプリケーション用の最も一般的なアプリケーション レベルのキャッシュであり、文字列、ハッシュ、リスト、セット、ソート セット、ストリームをサポートしています。選択したパターンによって、エッジケースでキャッシュがどのように動作するかが決まります。
キャッシュアサイド (遅延読み込み)
キャッシュアサイドは最も安全なデフォルト パターンです。アプリケーションは最初に Redis をチェックします。キャッシュがヒットすると、キャッシュされたデータが返されます。キャッシュミスが発生した場合、データベースにクエリを実行し、結果を TTL を使用して Redis に保存し、データを返します。
利点:
- 要求されたデータのみがキャッシュされます (未使用のデータに無駄なメモリがありません)
- データベース障害はキャッシュ ミスにのみ影響し、キャッシュ ヒットには影響しません。
- 実装と推論が簡単
短所:
- 各キーの最初のリクエストは常にデータベースにヒットします (コールド スタート)
- データベースの更新からキャッシュの有効期限までの間に、データが失効する可能性があります
ライトスルー
ライトスルー キャッシュでは、データベースへの書き込みが行われるたびに、キャッシュも即座に更新されます。アプリケーションは、同じ操作でデータベースと Redis の両方に書き込みます。
利点:
- キャッシュは常に最新です -- 古いデータウィンドウはありません
- 読み取りパフォーマンスは常に高速です (最初の書き込み後のキャッシュミスはありません)
短所:
- 書き込みレイテンシーが増加します (操作ごとに 2 回の書き込み)
- キャッシュには決して読み取られないデータが含まれる可能性があります (メモリの無駄)
- 一方の書き込みが成功し、もう一方の書き込みが失敗した場合は、慎重なエラー処理が必要です
ライトビハインド (ライトバック)
ライトビハインド キャッシュは Redis に即座に書き込みますが、データベースへの書き込みはバックグラウンド プロセスに延期します。これにより、書き込みレイテンシは短縮されますが、データベースの書き込みが完了する前に Redis に障害が発生した場合、データ損失のリスクが生じます。
慎重に使用してください -- このパターンは、金融取引や在庫数ではなく、時折のデータ損失が許容される分析カウンター、レート制限、およびセッション データに適しています。
キャッシュスタンピードの防止
キャッシュ スタンピードは、一般的なキャッシュ キーの有効期限が切れ、数百の同時リクエストがすべて同時にデータベースを再構築するためにクエリを実行すると発生します。これにより、データベースに過負荷がかかる可能性があります。
予防戦略:
- Stale-while-revalidate -- 1 つのリクエストがバックグラウンドでキャッシュを再構築している間に、わずかに古いデータを提供します
- ミューテックス ロック -- Redis SETNX を使用して、他のリクエストが待機するか古いデータを提供する間、1 つのリクエストだけがキャッシュを再構築するようにします。
- 確率的な早期有効期限 -- TTL 有効期限が切れる前にランダムに再計算し、再構築を有効期限に集中させるのではなく、時間の経過とともに分散させます。
TTL 戦略の設計
Time-to-Live (TTL) 値によって、データがキャッシュ内に留まる期間が決まります。短すぎると、過剰なキャッシュミスが発生します。長すぎると、古いデータが提供されてしまいます。
| データ型 | 推奨TTL | 理論的根拠 |
|---|---|---|
| ユーザーセッション | 30分(スライド) | セキュリティと UX のバランスをとる |
| 製品カタログ | 5~15分 | 商品は頻繁に変更されず、価格は鮮度が重要 |
| 検索結果 | 1~5分 | 在庫の更新に応じて結果が変化します |
| 静的コンテンツ (概要、FAQ) | 1~24時間 | コンテンツはめったに変更されません |
| レート制限カウンター | ウィンドウ サイズを一致させる | レート制限が機能するには正確である必要があります。 |
| 計算されたダッシュボード | 5~30分 | 鮮度と計算コストのバランスをとる |
| 機能フラグ | 30~60秒 | フラグ変更の迅速な伝達 |
スライド TTL と固定 TTL
固定 TTL は、作成後の設定された時間にキーを期限切れにします。スライディング TTL は、キーにアクセスするたびに有効期限をリセットします。セッション データにはスライディング TTL を使用し (アクティブなセッションを維持)、コンテンツ キャッシュには固定 TTL (ソースからの定期的な更新を確保) を使用します。
HTTP キャッシュ ヘッダーの詳細
HTTP キャッシュは、ブラウザー、CDN、プロキシ、ロード バランサーのすべてが同じヘッダーを理解するなど、あらゆるレイヤーで機能するため強力です。
キャッシュ制御ディレクティブ
- パブリック -- 任意のキャッシュ (ブラウザ、CDN、プロキシ) に応答を保存できます。
- プライベート -- ブラウザのみがキャッシュできます (CDN やプロキシは不可) -- 認証された応答に使用します
- no-cache -- 応答をキャッシュしますが、使用する前にサーバーで再検証します (誤解を招く名前 -- キャッシュします)
- no-store -- キャッシュをまったく行いません (銀行ページなどの機密データ)
- max-age=N -- キャッシュは N 秒間有効です
- s-maxage=N -- CDN/プロキシ キャッシュ期間 (共有キャッシュの max-age をオーバーライドします)
- stale-while-revalidate=N -- バックグラウンドで再検証している間、古いコンテンツを N 秒間提供します
- 不変 -- コンテンツは決して変更されません (コンテンツでハッシュされた URL で使用します)
ETag と条件付きリクエスト
ETag はコンテンツベースのキャッシュ検証を提供します。サーバーは応答コンテンツのハッシュを生成し、ETag ヘッダーとして送信します。後続のリクエストでは、ブラウザーは If-None-Match ヘッダーで ETag を送信します。コンテンツが変更されていない場合、サーバーは 304 Not Modified (本文なし) で応答し、帯域幅を節約します。
コンテンツが予期せず変更され、TTL ベースのキャッシュが積極的すぎるか保守的すぎる場合は、API 応答に ETag を使用します。
ヘッダーを変更する
Vary ヘッダーは、応答が特定の要求ヘッダーに依存することをキャッシュに伝えます。たとえば、Vary: Accept-Encoding は、gzip バージョンと Brotli バージョンが別々にキャッシュされることを意味します。 Vary: Accept-Language は、異なる言語バージョンを個別にキャッシュします。
Vary には注意してください。さまざまなヘッダーの一意の組み合わせごとに、個別のキャッシュ エントリが作成されます。ユーザーごとに異なる Cookie があるため、Vary: Cookie は事実上キャッシュを無効にします。
キャッシュ無効化戦略
キャッシュの無効化は、コンピューター サイエンスにおける 2 つの困難な問題のうちの 1 つとして有名です。目標は、ソース データが変更されたときに、古い読み取りや不要なキャッシュ ミスを引き起こすことなく、キャッシュされたデータを削除または更新することです。
TTL ベースの有効期限
最も単純で信頼性の高い無効化戦略。キャッシュされたすべてのキーに TTL を設定し、TTL ウィンドウ内でデータがわずかに古くなっている可能性があることを受け入れます。ほとんどのユースケースでは、5 分間の TTL により、鮮度とパフォーマンスのバランスが優れています。
イベント駆動型の無効化
データベース レコードが変更されたときに、キャッシュの削除をトリガーするイベントを発行します。これにより、ほぼ瞬時に新鮮さが得られますが、複雑さと障害モードが追加されます。イベントが失われた場合 (ネットワークの問題、キューの障害)、キャッシュは TTL が期限切れになるまで古いデータを提供します。
在庫数や価格設定などの重要なデータにはイベント ドリブンの無効化を使用し、それ以外はすべて TTL に依存します。
タグベースの無効化
一部のキャッシュ システムでは、ラベルによるキャッシュ エントリのタグ付けをサポートしています。タグを無効にすると、そのタグを持つすべてのエントリが削除されます。これは、特定のエンティティに関連するすべてのキャッシュされたデータ (たとえば、製品カタログが更新されたときのすべての製品関連のキャッシュ) を無効にする場合に役立ちます。
よくある質問
何をキャッシュするかをどのように決定すればよいですか?
頻繁に読み取られ、計算にコストがかかり、短期間の失効を許容するデータをキャッシュします。製品カタログ ページ、ユーザー権限、計算されたダッシュボード メトリック、および構成データが優れた候補です。ショッピング カート、リアルタイムの在庫数、および金融トランザクションは、通常、キャッシュされないか、イベント駆動型の無効化で非常に短い TTL を使用する必要があります。
Redis がダウンするとどうなりますか?
キャッシュ アサイド パターンを使用すると、アプリケーションはフォールバックしてデータベースに直接クエリを実行します。応答時間は長くなりますが、アプリケーションは引き続き機能します。キャッシュ ミスを適切に処理するようにアプリケーションを設計します。Redis は単一障害点ではなく、パフォーマンスを最適化する必要があります。
Redis にはどのくらいのメモリを割り当てる必要がありますか?
キャッシュ ヒット率とメモリ使用量を監視します。ヒット率が 95% を超え、メモリ使用率が 80% 未満であれば、サイジングが適切であることを示します。ヒット率が 90% を下回る場合は、より多くのメモリが必要か、TTL が短すぎます。ほとんどのアプリケーションでは 1 ~ 2 GB から開始し、監視データに基づいて拡張します。
Redis と Memcached のどちらを使用するべきですか?
ほとんどのアプリケーションにとって、Redis がデフォルトの選択肢として適しています。より多くのデータ型、永続化オプション、イベント駆動型無効化のためのパブリッシュ/サブスクライブ、およびアトミック操作のための Lua スクリプトをサポートしています。 Memcached は、非常に大規模な純粋なキーと値のキャッシュの場合、よりシンプルでわずかに高速ですが、Redis はより多くのユースケースをカバーします。
導入後に古いデータが提供されるのを防ぐにはどうすればよいですか?
キャッシュ キーにバージョン識別子を含めます (たとえば、デプロイメント バージョンまたはスキーマ バージョンを伴うプレフィックス キー)。デプロイすると、新しいバージョンは新しいキャッシュ キーを使用し、古いキーは TTL 経由で自然に期限切れになります。あるいは、アプリケーションがコールド キャッシュを適切に処理する場合は、展開時にキャッシュ全体をフラッシュします。
次は何ですか
まず、静的アセットとパブリック ページに HTTP キャッシュ ヘッダーを実装します。これにより、アプリケーションに変更を加えることなく、パフォーマンスが即座に向上します。次に、最も高価なデータベース クエリと API エンドポイントに Redis キャッシュを追加します。
パフォーマンス最適化の全体像については、ビジネス プラットフォームのスケーリング に関する柱ガイドを参照してください。キャッシュにフィードするデータ ソースを最適化するには、データベース クエリの最適化 に関するガイドをお読みください。
ECOSIRE は、Odoo ERP および Shopify で実行されるプラットフォーム用のキャッシュ アーキテクチャを実装します。キャッシュ戦略のレビューについては、チームにお問い合わせください。
ECOSIRE によって発行 — Odoo ERP、Shopify eCommerce、OpenClaw AI にわたる AI を活用したソリューションで企業のスケールアップを支援します。
執筆者
ECOSIRE Teamテクニカルライティング
ECOSIRE のテクニカルライティングチームは、Odoo ERP、Shopify による EC、AI エージェント、Power BI による分析、GoHighLevel による自動化、そしてエンタープライズソフトウェアのベストプラクティスを扱っています。私たちのガイドは、企業が十分な情報に基づいてテクノロジーを判断できるよう支援します。
関連記事
コンポーザブル コマース: e コマース アーキテクチャの未来
コンポーザブル コマースと MACH アーキテクチャを探ります。API ファーストのヘッドレス コンポーネントがどのようにモノリシック プラットフォームを置き換え、より高速でより柔軟な e コマースを可能にするかについて説明します。
データ メッシュ アーキテクチャ: エンタープライズ向けの分散型データ
データ メッシュ アーキテクチャに関する包括的なガイド。原則、実装パターン、組織の要件、およびスケーラブルなドメイン主導のデータ所有権を実現する方法について説明します。
k6 負荷テスト: 起動前に API のストレス テストを行う
Node.js API の k6 負荷テストをマスターします。仮想ユーザーの増加、しきい値、シナリオ、HTTP/2、WebSocket テスト、Grafana ダッシュボード、CI 統合パターンをカバーします。
パフォーマンスとスケーラビリティのその他の記事
Webhook のデバッグと監視: 完全なトラブルシューティング ガイド
障害パターン、デバッグ ツール、再試行戦略、監視ダッシュボード、セキュリティのベスト プラクティスを網羅したこの完全なガイドを利用して、Webhook デバッグをマスターしてください。
k6 負荷テスト: 起動前に API のストレス テストを行う
Node.js API の k6 負荷テストをマスターします。仮想ユーザーの増加、しきい値、シナリオ、HTTP/2、WebSocket テスト、Grafana ダッシュボード、CI 統合パターンをカバーします。
Nginx 実稼働構成: SSL、キャッシュ、およびセキュリティ
Nginx 実稼働構成ガイド: SSL 終端、HTTP/2、キャッシュヘッダー、セキュリティヘッダー、レート制限、リバースプロキシセットアップ、Cloudflare 統合パターン。
Odoo パフォーマンス チューニング: PostgreSQL とサーバーの最適化
Odoo 19 のパフォーマンス チューニングに関する専門ガイド。 PostgreSQL の構成、インデックス作成、クエリの最適化、Nginx キャッシュ、エンタープライズ展開のためのサーバーのサイジングについて説明します。
本番環境での AI エージェントのテストと監視
実稼働環境で AI エージェントをテストおよび監視するための完全なガイド。 OpenClaw 導入の評価フレームワーク、可観測性、ドリフト検出、インシデント対応について説明します。
OpenClaw を使用したコンプライアンス監視エージェント
継続的なコンプライアンス監視のために OpenClaw AI エージェントを導入します。規制チェック、ポリシーの適用、監査証跡の生成、コンプライアンスレポートを自動化します。