システムデザインの概念（part4: Cache）

### キャッシングの基本

CPUキャッシュは、RAMやディスクよりも高速に読み書き操作を実行できる、コンピュータの中で最も高速な記憶装置です。キャッシュはデータのコピー過程であり、RAMやディスクからデータをCPUのキャッシュにコピーすることで、読み書き速度を向上させます。しかし、キャッシュの容量は限られており、通常は数キロバイトから数メガバイト程度しかありません。そのため、オペレーティングシステムはキャッシュに保存するデータを慎重に選ぶ必要があります。単一のコンピュータ内キャッシュに加えて、分散システムでもキャッシュが広く使用されています。

**キャッシュの動作方式を様々な視点から見てみましょう：**

まず、クライアントの視点から：リクエストを受け取った後、ブラウザはまずメモリキャッシュをチェックします。存在しない場合は、ディスクキャッシュをチェックし、過去の履歴情報が存在するかを確認します。ディスクにも存在しない場合は、ネットワークリソースへのリクエストが行われます。

「キャッシュヒット率」という指標があります。キャッシュが見つかるとヒット、見つからないとミスと呼ばれます。キャッシュヒット率は、キャッシュヒット数 /（キャッシュヒット数 + キャッシュミス数）で計算されます。

次に、サーバーの視点から：サーバーのディスクは例えばデータベースであり、キャッシュはRedisのようなキャッシュデータベースです。

サーバーがデータをキャッシュする際の複雑さと、異なるキャッシュモードの実際の動作方式：

1. **ライトバックキャッシュ（Write-back cache）**：ライトバックキャッシュモードでは、データはまずキャッシュに書き込まれ、キャッシュが満杯になった時にのみディスクに書き込まれます。これにより、データの更新時にキャッシュのみを更新し、ディスクへの頻繁なアクセスを減らすことができます。しかし、この場合、キャッシュが失われるとデータが失われる可能性があるため、許容度を考慮する必要があります。

2. **ライトスルーキャッシュ（Write-through cache）**：ライトスルーキャッシュモードでは、データはキャッシュとディスクの両方に同時に書き込まれます。データがアクセスされるかどうかに関わらず、これによりキャッシュとディスクのデータの一貫性を確保し、不一致の問題を避けることができますが、メモリバスの負荷が増加する可能性があります。

3. **ライトアラウンドキャッシュ（Write-around cache）**：ライトアラウンドキャッシュモードでは、新しいデータはキャッシュではなく直接ディスクに書き込まれます。データがアクセスされた場合にのみキャッシュに追加されます。これによりキャッシュスペースを節約できますが、初回アクセス時の遅延が高くなる可能性があります。

4. **キャッシュクリアリングポリシー**：キャッシュクリアリングポリシーは、キャッシュが満杯になった時にどのデータをクリアするかを決定します。一般的なポリシーにはFIFO（先入先出）、LRU（最近最少使用）、LFU（最不頻使用）などがあります。

5. **LRU（最近最少使用）ポリシー**：LRUキャッシュポリシーは、データの最近の使用状況に基づいてキャッシュをクリアします。長期間アクセスされていないデータが最もクリアされやすいと見なされます。このポリシーは、データのホット度を維持する必要があるシナリオに適しています。例えば、Twitterのホットなツイートなどです。

6. **LFU（最不頻使用）ポリシー**：LFUキャッシュポリシーは、データのアクセス頻度に基づいてキャッシュをクリアします。使用頻度が低いデータがクリアされる可能性があります。しかし、場合によってはLFUポリシーにも問題が生じる可能性があります。例えば、過去に頻繁にアクセスされていた古いデータが、いつまでもクリアされないことがあります。

以上のように、サーバーがキャッシュポリシーを選択する際には、データのアクセス頻度、メモリとディスクの負荷、データの一貫性のニーズを考慮する必要があります。適切なキャッシュポリシーを選択することで、システムの性能と応答速度を向上させることができます。ただし、最も一般的に使用されるのはLRUポリシーです。

### CDN（コンテンツ配信ネットワーク）

コンテンツ配信ネットワーク（CDN）は、世界中に分散して配置されたエッジキャッシュサーバーのグループです。これにより、コンテンツをユーザーにより迅速に配信することができます。主に静的ファイル（HTML、CSS、JavaScriptなど）を扱います。

現代のエッジサーバーは、動的コンテンツを本当に提供することを可能にしています。これは、サーバーレスのJavaScript関数を介して実現され、デバイスの種類、時間、ユーザーの位置などの異なる入力を受け取り、動的コンテンツをキャッシュします。

また、CDNはロードバランサーに似た機能も提供できます。例えば、あるCDNサーバーに障害が発生した場合、次に近いサーバーにリダイレクトされます。

**プッシュCDN**：

プッシュCDNは、静的で頻繁に変更されないコンテンツを持つウェブサイトに特に適しています。プッシュCDNでは、新しいデータがオリジンサーバーに追加されると、すぐにすべてのキャッシュサーバーにプッシュされます。

プッシュCDNを効果的に利用するためには、コンテンツが広くリクエストされる必要があります。プッシュCDNはコンテンツをすべてのキャッシュサーバーに分配するため、ユーザーからリクエストされないコンテンツがあれば、効率が低下する可能性があります。

プッシュCDNに適した典型的なユースケースは、グローバルなビデオコンテンツをホストするウェブサイトです。プッシュCDNの利点は、ユーザーがオリジンサーバーからコンテンツを待つ必要がないことです。すべてのユーザーリクエストはキャッシュヒットをもたらし、データはすでにキャッシュサーバーにコピーされています。コンテンツ所有者は、どのコンテンツをCDNにプッシュするかを完全に自由に決定できますが、サーバー上のファイルを継続的に更新および維持する責任も負います。

**プルCDN**：

クライアントやユーザーがアクセスしようとしているデータがCDN上に存在しない場合、キャッシュのプロセスに似たことが起こります。まずキャッシュサーバーをチェックし、データが存在しない場合はキャッシュサーバーがオリジンサーバーからデータを取得し、将来のリクエストのためにキャッシュします。

プッシュCDNに比べて、プルCDNは必要に応じてオリジンサーバーからコンテンツを取得するため、前述したキャッシュの基本概念により合致しています。

例えば、Twitterのようなウェブサイトは、プルCDNの理想的な利用者です。Twitterは毎秒大量のコンテンツを生成します。Twitterチームにとって、すべてのコンテンツを事前にCDNにプッシュするのは大きな負担となるでしょう。代わりに、ユーザーがサーバーからコンテンツをリクエストすると、CDNは自動的にサーバーから取得してキャッシュに保存します。

さらに、異なる地域のユーザーは異なるコンテンツをリクエストする可能性があることに注意してください。例えば、あるTwitterプロフィールが一地域では他の地域よりも人気があるかもしれません。そのため、異なる地域のCDNは各地域のオーディエンスに合わせた異なるコンテンツを持つことがあります。

これは、地理特有のコンテンツを持つ大規模なプラットフォームにより関連していますが、依然として興味深い技術的概念です。そのため、すべてのコンテンツを事前にCDNにプッシュすることは、リソースを過度に消費する可能性がありますが、プルCDNアプローチはユーザーリクエストに応じて動的にコンテンツを取得してキャッシュすることができます。