編集部注:高容量・高可用性キャッシュに関するシリーズの第1回です:
- NGINX Plusキャッシュクラスターによる共有キャッシュ:第1部(本記事)
- NGINX Plusキャッシュクラスターによる共有キャッシュ、パート 2
この投稿は、当初取り上げていた独立した拡張ステータスモジュールに代わり、同モジュールを非推奨とするNGINX Plus APIについて記載するよう更新されました。
NGINXまたはNGINX Plusを使用して、大容量で高可用性のキャッシュクラスターを構築するにはどうすればよいでしょうか。本記事は、この目標を達成するための別のアプローチを紹介する全2回シリーズの第1回です。第2回は上記のリンクからご覧いただけます。(特に記載がない限り、ここで紹介するアプローチはNGINX Open SourceとNGINX Plusの両方に同様に適用できますが、簡潔にするため、以降はNGINX Plusとのみ表記します。)
NGINX Plusキャッシュの概要
NGINX Plusは、オリジンサーバーとリモートクライアントの間に配置され、プロキシキャッシュサーバーとして動作できます。NGINX Plusは、オリジンサーバーへのトラフィックを管理し、共通して使用される変更のないリソースをキャッシュ(保存)します。これにより、これらのリソースがリクエストされた際にNGINX Plusがクライアントへ直接応答できるため、オリジンサーバーの負荷が軽減されます。NGINX Plusのプロキシキャッシュは通常、オリジンサーバーに隣接するデータセンターに導入されますが、世界各地に分散したPoPにCDNのような形で導入することもできます。
コンテンツキャッシュは、意外に複雑なトピックです。この記事を読み進める前に、基本的なキャッシュ手法をいくつか理解しておくことをお勧めします。
- NGINX Plusキャッシュの仕組み – 基本設定と、キャッシュローダープロセスおよびキャッシュマネージャープロセスの役割
- キャッシュ時間の微調整 – マイクロキャッシュなどの手法を実装し、コンテンツのキャッシュ方法と、期限切れ時の更新方法を制御
NGINX Plusがキャッシュに共有ディスクを使用しない理由
各NGINX Plusサーバーは、独立したWebキャッシュサーバーとして動作します。複数のNGINX Plusサーバー間でディスクベースのキャッシュを共有する技術的な手段はありません。これは意図的な設計上の判断です。
レイテンシーが高く、信頼性に問題が生じる可能性のある共有ファイルシステムにキャッシュを保存することは、適切な設計とはいえません。NGINX Plusはディスクレイテンシーの影響を受けやすく、スレッドプール機能によってread()およびwrite()の処理をメインスレッドからオフロードしても、ファイルシステムが低速でキャッシュI/Oが多い場合、大量のスレッドによってNGINX Plusが過負荷になる可能性があります。また、複数のNGINX Plusインスタンス間で一貫性のある共有キャッシュを維持するには、キャッシュへの書き込み、読み取り、削除など、重複するキャッシュ操作を同期するために、クラスター全体のロックが必要になります。さらに、キャッシュでは信頼性と安定したパフォーマンスが最も重要ですが、共有ファイルシステムは信頼性の低下や予測不能なパフォーマンスの要因となります。
複数のNGINX Plusサーバー間でキャッシュを共有する理由
ファイルシステムの共有はキャッシュに適した方法ではありませんが、複数のNGINX Plusサーバー間でコンテンツをキャッシュすることには十分な理由があり、それぞれに対応する手法があります。
- 非常に大容量のキャッシュを構築することが主な目的であれば、キャッシュを複数のサーバーにシャーディング(分割)します。この手法については、本記事で説明します。
- オリジンサーバーの負荷を最小限に抑えながら高可用性を実現することが主な目的であれば、高可用性の共有キャッシュを使用します。この手法については、関連記事(近日公開)をご覧ください。

キャッシュのシャーディング
キャッシュのシャーディングとは、キャッシュエントリを複数のWebキャッシュサーバーに分散するプロセスです。NGINX Plusのキャッシュシャーディングでは、コンシステントハッシュアルゴリズムを使用して、キャッシュエントリごとに1台のキャッシュサーバーを選択します。図は、3台のサーバーに分散されたキャッシュ(左図)で、1台のサーバーが停止した場合(中央図)と、別のサーバーを追加した場合(右図)に何が起こるかを示しています。

キャッシュの総容量は、各サーバーのキャッシュ容量の合計です。各リソースをキャッシュするのは1台のサーバーのみであり、同じリソースの独立したコピーが複数作成されないため、オリジンサーバーへのアクセスを最小限に抑えられます。

このパターンにフォールトトレランスがあるのは、キャッシュサーバーがN台あり、そのうち1台に障害が発生しても、失われるキャッシュは全体の1/Nにとどまるためです。この「失われた部分」は、コンシステントハッシュによって、残りのN−1台のサーバーに均等に分散されます。一方、より単純なハッシュ方式では、キャッシュ全体が残りのサーバーに再分散されるため、再分散中はキャッシュのほぼすべてが失われます。
When you perform コンシステントハッシュ方式の負荷分散を行う場合、キャッシュキー(またはキーの構成に使用するフィールドのサブセット)をコンシステントハッシュのキーとして使用します:
upstream cache_servers { hash $scheme$proxy_host$request_uri consistent;
server red.cache.example.com;
server green.cache.example.com;
server blue.cache.example.com;
}受信トラフィックは、NGINX Plusのアクティブ/パッシブ高可用性ソリューション、ラウンドロビンDNS、またはkeepalivedなどの高可用性ソリューションを使用して、ロードバランサー(LB)層全体に分散できます。
シャード化キャッシュ構成の最適化
キャッシュシャーディング構成では、2つの最適化方法のいずれかを選択できます。
ロードバランサー層とキャッシュ層の統合
LB層とキャッシュ層を組み合わせることができます。この構成では、各NGINX Plusインスタンスで2つの仮想サーバーが稼働します。負荷分散仮想サーバー(図中の「LB VS」)は外部クライアントからのリクエストを受け付け、コンシステントハッシュを使用して、内部ネットワークで接続されたクラスター内のすべてのNGINX Plusインスタンスにリクエストを分散します。各NGINX Plusインスタンスのキャッシュ仮想サーバー(「Cache VS」)は、割り当てられたリクエストを内部IPアドレスで待ち受け、オリジンサーバーに転送してレスポンスをキャッシュします。これにより、すべてのNGINX Plusインスタンスがキャッシュサーバーとして機能し、キャッシュ容量を最大限に活用できます。

第1レベルの「ホット」キャッシュの設定
別の方法として、アクセスが非常に集中するコンテンツ向けにフロントエンドLB層に第1レベルキャッシュを構成し、大容量の共有キャッシュを第2レベルキャッシュとして使用できます。これにより、パフォーマンスが向上する可能性があります。また、第2レベルのキャッシュ層に障害が発生した場合でも、第1レベルキャッシュ内のコンテンツが徐々に期限切れになるのに伴ってコンテンツを更新すればよいため、オリジンサーバーへの影響を軽減できます。

キャッシュクラスターが非常に大量のホットコンテンツを処理している場合、容量の小さい第1レベルキャッシュでは、コンテンツの入れ替わりが非常に激しくなることがあります。つまり、限られたキャッシュ領域への需要が非常に高いため、コンテンツが後続のリクエストに1回も使用されないうちに、より新しくリクエストされたコンテンツ用の領域を確保するため、キャッシュから削除されます。
この状況を示す指標の1つは、書き込まれたコンテンツに対する配信されたコンテンツの比率が低いことです。これら2つのメトリクスは、NGINX Plus APIモジュールが報告する拡張統計に含まれています。これらは、組み込みのServedフィールドとWrittenフィールドに表示されます。場所は、Cachesタブにあるライブアクティビティ監視ダッシュボードです。(NGINX Plus APIモジュールとライブアクティビティ監視ダッシュボードは、NGINX Open Sourceでは利用できません。)
このスクリーンショットは、NGINX Plusがキャッシュから配信するコンテンツよりも多くのコンテンツをキャッシュに書き込んでいる状況を示しています。
![NGINX Plusのライブアクティビティ監視ダッシュボードの[Caches]タブには、キャッシュから読み出されるデータよりも書き込まれるデータの方が多いという望ましくない状況が表示されています](https://cdn.studio.f5.com/images/k6fem79d/translations-production/2f6d7cf080cb3819db7deb9272fbb8ebd3a5f69a-901x240.png)
この場合、最も頻繁にリクエストされるコンテンツのみを保存するように、キャッシュを細かく調整できます。proxy_cache_min_usesディレクティブは、このようなコンテンツの特定に役立ちます。
まとめ
複数のNGINXまたはNGINX Plus Webキャッシュサーバーにキャッシュを分散することで、非常に大容量でスケーラブルなキャッシュを効果的に構築できます。コンシステントハッシュにより高い可用性が確保されるため、いずれかのキャッシュに障害が発生しても、無効になるのはそのキャッシュが担当するコンテンツのみです。
この投稿の後編では、2台のNGINXまたはNGINX Plusキャッシュサーバーにキャッシュを複製する、別の共有キャッシュパターンについて説明します。総容量は1台のサーバーの容量に制限されますが、この構成は完全な耐障害性を備えており、キャッシュサーバーが利用できなくなっても、キャッシュされたコンテンツは失われません。
お使いのサーバーでキャッシュシャーディングをお試しください。今すぐ30日間の無料トライアルを開始するか、ユースケースについてご相談ください。
著者について

関連するブログ記事
チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。
AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。
JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。
F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。
NGINX PlusによるAWS Auto Scalingグループの負荷分散
新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります