キャッシュパージ実践ガイド:キャッシュキーからバリアント単位のパージまで
キャッシュをパージしたのに、まだヒットするのでしょうか。多くの場合、答えはキャッシュキーにあります。Yeap CDN のキャッシュキーの構築方法、クエリ文字列モードの動作、クエリ文字列の有無によって URL パージの削除対象がどう変わるかを解説します。
「キャッシュをパージしたのに、なぜ古いコンテンツが表示されるのでしょうか?」これは CDN の利用者から特によく寄せられる質問の1つで、ほとんどの場合、その答えはキャッシュキーにあります。パージしたオブジェクトと、訪問者がアクセスしているオブジェクトが、同じではない可能性があるのです。このガイドでは、まずキャッシュキーについて説明し、次に Yeap CDN のパージで何が削除されるのか、パージリクエストを裏側でどのように配信しているのかを詳しくご紹介します。
キャッシュキー:エッジがファイルを区別する仕組み
エッジノードは、レスポンスをキャッシュするときにキャッシュキーで識別します。キーは、おおむね次の要素で構成されます。
- 対象のホスト名。例:
www.example.com。 - 対象のパス。例:
/assets/app.js。 - ドメインに設定されたクエリモードに応じて生成される、正規化されたクエリ文字列。
- 必要に応じて、コンテンツエンコーディングなど、バリアントを区別する要素も含まれます。
2つのリクエストが同じキャッシュオブジェクトにヒットするのは、キーが完全に一致する場合だけです。そのため、/app.js?v=1 と /app.js?v=2 はデフォルトで別のオブジェクトになります。また、バージョンを示すパラメータを付けると、ブラウザも CDN も新しいファイルを取得するのはこのためです。
クエリ文字列のモード
コンソールの「CDN → ドメイン → キャッシュ」ページで、ドメインがクエリ文字列をどのように扱うかを選択できます。このページには、現在の設定に基づくキャッシュキーのプレビューもリアルタイムで表示されます。
| モード | 動作 | 適している用途 |
|---|---|---|
| 標準(すべて) | すべてのパラメータをキーに含めます。?a=3 と ?a=4 は別のオブジェクトになります | パラメータによってコンテンツが変わるサイト |
| 無視 | クエリ文字列を完全に無視します。どの組み合わせでも同じオブジェクトにヒットします | 純粋な静的アセット |
| 並べ替え | すべてのパラメータを名前順に並べ替えてキーに含めます。?b=2&a=1 と ?a=1&b=2 は同じオブジェクトを共有します | パラメータをさまざまな順序で送信するクライアント |
| 許可リスト | 指定したパラメータだけをキーに含めます | 一部のパラメータだけがコンテンツを変える場合 |
| 拒否リスト | 指定したパラメータを除外し、それ以外をすべて含めます | utm_source などのトラッキングパラメータを無視する場合 |
内部では、エッジは常にパラメータをデコードし、名前順に並べ替え、同じ名前が複数ある場合はその値も並べ替えたうえで、再エンコードしてからキーを構築します。そのため、パラメータを保持するどのモードでも、順序の違いだけでオブジェクトが重複することはありません。再エンコードも重要です。デコード後の値に含まれる & や = が曖昧な文字列を生まないようにすることで、異なる2つのリクエストが同じキャッシュキーにならないようにしています。
よくある最適化の例をご紹介します。マーケティング用のリンクにはさまざまなトラッキングパラメータが付いていることが多く、組み合わせが異なるたびに新しいオブジェクトが作られ、ヒット率が下がります。拒否リストモードでこれらを除外すると、通常はヒット率が目に見えて改善します。
パージで実際に削除されるもの
キャッシュ設定ページの右上にある「キャッシュをパージ」をクリックし、2つの選択肢から1つを選びます。
すべてパージ
すべてのエッジノードから、対象ドメインのキャッシュオブジェクトをすべて削除します。大規模なリリースや、何が変わったかわからない場合に使用してください。ただし、その後しばらくはすべてのリクエストがオリジンに向かうため、一時的にオリジンの負荷が増加します。
URL を指定してパージ
完全な URL を1行に1つずつ入力します。パージの動作を理解するうえで重要なのは、次のルールです。
- クエリ文字列がない場合、たとえば
https://www.example.com/listを指定すると、そのパスのすべてのクエリ文字列バリアントを削除します。/list、/list?page=2、/list?page=3なども含まれます。 - クエリ文字列がある場合、たとえば
https://www.example.com/list?page=2を指定すると、その1つのバリアントだけを削除します。/list?page=3はキャッシュに残ります。
クエリ文字列を指定してパージする場合、キャッシュキーの構築とまったく同じルール(同じモード、同じ並べ替え、同じエンコード)で正規化されます。そのため、キャッシュされたリクエストが ?b=2&a=1 であっても、?a=1&b=2 と入力すれば、対象を正確にパージできます。
この動作は、ユーザーのフィードバックを受けて実装しました。初期のパージインデックスはホストとパスだけを比較していたため、?a=3 をパージして成功と表示されても、オブジェクトへのヒットが続くことがありました。キャッシュキーにはクエリ文字列が含まれているのに、パージ時の照合には含まれていなかったためです。現在は、すべてのパージインデックスエントリに正規化済みのクエリ文字列を記録し、バリアント単位で照合しています。
エッジのパージモデルは、プレフィックス、ワイルドカード、タグによる照合にも対応しています。現在、コンソールではサイト全体のパージと URL を指定したパージを利用できます。
パージリクエストがすべてのノードに届く仕組み
確定すると、コンソールはほぼ即座に応答を返します。HTTP リクエストの処理中に、同期的にパージを配信しているわけではないためです。
- コントロールプレーンは、パージジョブ(ドメインとパスの一覧)を Redis ベースのバックグラウンドキューに入れ、すぐに応答を返します。
- キューのコンシューマーは、そのドメインを配信するエッジノードへジョブを並列配信し、失敗した場合は自動で再試行します。
- キュー自体が利用できない場合は、コントロールプレーンが同期配信にフォールバックするため、パージが失われることはありません。
エッジノードでパージを完了するには、2つの処理が必要です。まず、パージインデックスから一致するストレージキーをすべて探し、次に、それらのオブジェクトをキャッシュストレージから削除するとともに、メモリ内のホット層からも削除します。複数の配信チャネルが互いに干渉しないよう、非同期コンテキストでストレージから確実に削除できるチャネルだけがインデックスを変更します。その他のチャネルは、インデックスを変更せずに照合を行い、ホット層だけをクリアします。どのチャネルが先に到着しても、最終的にパージが完了します。
確認方法
エッジのレスポンスには X-Cache-Status ヘッダーが含まれます。パージ後に curl で確認してください。
curl -sI "https://www.example.com/list?page=2" | grep -i x-cache-status
# first request after the purge: X-Cache-Status: MISS
# request again: X-Cache-Status: HIT
パージ後も古いコンテンツが表示される場合は、次の順序で確認してください。
- 原因はブラウザキャッシュでしょうか。エッジのパージでは、訪問者のブラウザにすでにキャッシュされているコピーは削除されません。curl またはプライベートウィンドウでテストしてください。
- 入力した URL のホスト名は、実際のリクエストと同じでしょうか。
example.comとwww.example.comのキャッシュは別です。 - オリジンがまだ古いコンテンツを配信していないでしょうか。パージ後、エッジはオリジンから再取得します。オリジンの前段に別のキャッシュがある場合は、そちらも更新する必要があります。
ベストプラクティス:パージへの依存をできる限り減らす
パージは便利なツールですが、静的アセットで最も確実なのは、コンテンツが変わると URL も変わるようにすることです。
app.3f9a1c.jsのようにコンテンツのハッシュを含むファイル名を使い、キャッシュの有効期間を長く設定します。新しいバージョンには新しい URL が付くため、パージは不要です。- 入口となる HTML ページのキャッシュ有効期間は短くし、新しいアセットの URL がすぐに反映されるようにします。
- パージが必要な場合は、URL を指定したパージを優先し、サイト全体のパージは広範な変更のときに使います。
キャッシュキーを理解すれば、パージを推測に頼る必要はなくなります。パージしたキーに対応するオブジェクトが削除されるのです。
Yeap Cloud で開発を始める
新規アカウントで DNS と CDN の無料プランをご利用いただけます。
続きを読む
OpenAI SDK で始める Yeap LLM API
Yeap LLM API は OpenAI 互換です。SDK はそのまま、base_url を https://llm.yeap.cloud/v1 に変更して利用できます。キーの作成、Python と Node.js の例、ストリーミング、埋め込みベクトル、キーごとのクォータ・モデル制限・IP 制限を解説します。
エッジにおける TLS セッション再開と HTTP/3
セッション再開により、再訪問者は TLS のフルハンドシェイクを省略できます。再起動後もチケット鍵を保持する必要がある理由、安全なローテーションの方法、エッジの HTTP/3 が既存のリクエスト処理パイプラインを再利用する仕組みを解説します。
10 Minutes で Web サイトに Yeap CDN と無料の HTTPS を導入する
既存サイトへの Yeap CDN 導入を順を追って解説します。ドメインの追加、オリジン設定、CNAME または NS での接続、無料の Let's Encrypt 証明書の取得、SSL モードの選択、HTTPS の強制、curl での確認までをご紹介します。