odkkk
VODK プロジェクトでのマルチレイヤー キャッシュ アーキテクチャの実践
ウェブ開発 · · 読むのに 4 分かかります

VODK プロジェクトでのマルチレイヤー キャッシュ アーキテクチャの実践

ビデオ集約サイト tv.odkkk.com がどのようにして複数の不安定なデータ ソースをスムーズなサイトに変えたのか - その背後にある多層キャッシュのアイデアについて話しましょう。

この Web サイトは何をするものですか?

tv.odkkk.com は私が作った小さなサイトです。簡単に言うと、ビデオ集約ポータルです。映画ソース自体を保存するのではなく、インターネット上の複数のリソース サイトからコンテンツを収集するため、ユーザーは映画を見つけるために行ったり来たりする必要がなくなります。

主に次の 3 つのことを行います。

  • ネットワーク全体を一度に検索: 映画のタイトルを入力し、バックグラウンドで複数のリソース サイトに移動して再度質問し、結果を結合し、重複を削除し、並べ替えて返します。ユーザーには、5 つまたは 6 つのサイト間でタイトルが貼り付けられるのではなく、1 つのきれいなリストが表示されます。
  • 完全な情報: リソース ステーションから返されるデータは通常非常に大まかで、タイトルと再生アドレスのみであることがよくあります。これらを Douban に持って行き、評価、紹介、ポスターをチェックし、すべての結果を適切なものにするために Banguchi に関する情報を補足します。
  • どこを見たかを記憶: 再生の進行状況、検索履歴、お気に入りはすべてアカウントに従っており、ページを変更しても失われることはありません。

複雑そうに聞こえませんが、実際に実行してみると、問題は関数自体ではなく、データ ソースの信頼性が低すぎるという事実であることがわかります。リソース サイトが頻繁にタイムアウトになり、ブロックされます。 Douban はブラウジングしすぎると 403 を取得しますが、ホームページの推奨事項には先週のコンテンツが常に表示されるわけではありません。クリックするたびにソースに直接アクセスしてデータを取得すると、エクスペリエンスは非常に悪くなります。数秒で開く場合もあれば、回転に時間がかかる場合もあり、エラーが直接報告される場合もあります。

したがって、このWebサイトが使えるかどうかは、フロントエンドの見た目ではなく、その上流の「風」をデータ層に隠し、ユーザーが常にスムーズだと感じられるかどうかが鍵となります。これは、次のキャッシュ アーキテクチャによって解決される問題です。

基本的な考え方: データはユーザーに近いほど良い

データ層全体は、CPU キャッシュの概念を、最速のものから最も遅いものまで、層ごとに借用しています。

请求 → 边缘缓存 → 热数据缓存 → 持久存储 → 上游源站

各レベルは失敗した場合にのみ質問し、ヒットした場合は直接戻ります。これにより、応答が最大化されるだけでなく、上流への圧力も最小限に抑えられます。レイヤーごとに説明しましょう。

最初の層: エッジ キャッシュ

最も外側は CDN エッジ ノードです。同じリクエストに対して、誰かが最近リクエストしたものである限り、エッジノードは私のサーバーにまったく到達せずに、最後のレスポンスをそのまま直接返します。これは、毎回メイン倉庫に行かなくても、階下の食堂に売れ筋商品を買いだめするようなものです。

ここにちょっとしたトリックがあります。期限切れの応答を最初に返し、バックグラウンドで静かに更新します。ユーザーが取得するのは「前の秒の古いデータ」ですが、次の秒に更新されます。更新は常に秒単位で開始されるため、ソースが返されるのを待つ必要はありません。

2 番目の層: ホット データ キャッシュ

エッジ キャッシュがミスし、リクエストがアプリケーション層に到達します。ここには、最近頻繁にアクセスされたデータ専用のメモリレベルの高速キャッシュがあります。

これの最も賢い点は、自身の人気度を判断することです。データへのアクセスが増えるほど、そのデータはより長く保持されます。受信したばかりのコールド データは 1 分間しか保持されませんが、繰り返しクリックされ始めると、自動的に数分、10 分、または 30 分に延長されます。次に、誰も読まないコンテンツはすぐに期限切れになり、スペースを占有します。

その結果、人気のあるコンテンツが永続的になればなるほど、人気の低いコンテンツは自然に淘汰されていきます。 「どれを残すべきか」を人々が推測する必要はなく、訪問者が自分で投票します。

さらに細かいことですが、データを書き込む際に「バックアップコピー」を保存しますが、有効期限はオリジナルの5倍です。元のコピーの有効期限が切れてソースに戻される場合でも、ユーザーはローディング サークルを見つめる代わりに、少なくとも古いデータを完全に取得できます。

3 番目の層: 永続ストレージ

ホット キャッシュ データは有効期限が切れても実際には消えません。永続ストレージの層から「ウォームアップ」されます。このレイヤーは長期間保存されます。これはオフライン スナップショットに相当します。たとえ上流サイトが今日完全にダウンしたとしても、最後にキャプチャされたデータがまだ残っています。最大でも、エラー ページではなく、わずかに古いコンテンツがユーザーに表示されます。

ここでは、無意味なトスを避けるために 2 つの小さなことを行いました。

まず、内容が実際に変更された場合にのみ上書きされます。各書き込みの前に、「フィンガープリント」が計算され、比較されます。内容が変わらない場合は、データ自体は書き換えず、アクセス時間と回数のみが更新されます。このようにして、繰り返しアクセスされるが内容が変わらない人気の映画が、毎日データベースに書き込まれて無駄になることはありません。

次に、新しいデータを更新する必要があります。永続化レイヤーは永続的に保持されますが、ホームページの推奨事項など、常に古いデータを供給できないものもあります。1 週間前のリストを常に表示するのは退屈でしょう。そのため、データの種類ごとに保存期限が設定されています。たとえば、ホームページの推奨事項は 1 日に 1 回更新する必要があり、検索結果はより長く保存できます。有効期間が経過すると、永続的なレイヤーが存在する場合でも、ソースに移動して別のレイヤーを取得する必要があります。

第 4 層: 上流起点局

本当にここまで到達できた場合は、最初の 3 つのレベルがすべて失敗したことになります。今こそリソースステーションのドアを実際にノックするときです。プルバックされた新しいデータは、ホット キャッシュと永続化レイヤーに同時に詰め込まれ、書き込みが完了する前にユーザーに応答します。次回同じリクエストが行われると、キャッシュから直接ヒットされます。

邪魔にならないライブラリを作成する

永続層にデータを書き込むと、応答が遅くなる可能性が最も高くなります。そこで私は書き込みを「非同期後」にしました。まずデータをユーザーに返し、それをバックグラウンドでゆっくりとデータベースにドロップします。データベースの書き込みに失敗しても、このアクセスには影響しません。せいぜい、次回ソースがもう一度返される程度です。

「ユーザーが速いと感じるかどうか」と「データが安全に保存されているかどうか」を区別する場合、このトレードオフには価値があります。データベースが遅ければユーザーは無関心になりますが、応答が 0.5 秒遅かったら、ユーザーはすぐにイライラしてしまいます。

## 効果

このアーキテクチャを実行した後、最も直観的なポイントは次の 2 つです。

1 つは 高速 です。ホームページは基本的に数秒で開き、検索には基本的に 100 ミリ秒もかかりません。リクエストの大部分はアップストリームに到達することはありません。

2つ目は安定性です。現在、特定のリソース サイトで問題が発生していますが、ホット キャッシュまたは永続層にあるため、ユーザーにはわかりませんが、データが少し古いためです。回復すると、次回クロールされたときに当然更新されます。

最後に書きます

このプロジェクトを完了してから、私の「キャッシュ」に対する見方は大きく変わりました。以前はキャッシュは単に「結果を次回より速く保存する」ことだと思っていましたが、今ではむしろユーザーにとって上流の不確実性を消化するようなものだと考えています。速度は単なる副産物であり、安定性こそが解決すべき真の問題なのです。

優れたキャッシュ戦略は、すべてのデータを永続的に保存するのではなく、ホット データを永続的に保存し、コールド データを復元し、期限切れのデータを更新できるようにすることです。

関連記事