Uenishi.Web

大阪に生息しているプログラマーのブログ

キャッシュとはなんぞや

はじめに

現在フロントエンド中心にお仕事をしているエンジニアです。

今まで何となくで理解していた「キャッシュ」の基本的な知識を(完全に)理解するための記事です。

キャッシュっていろんなところに使われていますよね。

お金のことも「キャッシュ」とか言うし、お金を引き出すカードは「キャッシュカード」だし。

PCやアプリケーションにおいても、サーバーキャッシュや、ブラウザキャッシュなどさまざまな「キャッシュ」があります。

ここではひとつひとつ整理しつつ、Webフロントエンド開発に関連するキャッシュを中心にして、引用などをもとにまとめていきます。

キャッシュとは

まずは引用します。

キャッシュ(英語: cache)は、CPUのバスやネットワークなど様々な情報伝達経路において、ある領域から他の領域へ情報を転送する際、その転送遅延を極力隠蔽し転送効率を向上するために考案された記憶階層の実現手段である[要出典]。実装するシステムに応じてハードウェア・ソフトウェア双方の形態がある(以下、コンピュータのプログラムなども含め全ての転送すべき情報をデータと表す)。

引用: https://ja.wikipedia.org/wiki/キャッシュ_(コンピュータシステム)

次のアーキテクチャスタイルはキャッシュ(Cache)です。キャッシュとは、リソースの鮮度に基づいて、一度取得したリソースをクライアント側で使いまわす方式です(注4)。キャッシュの利点は、サーバとクライアントの間の通信を減らすことでネットワーク帯域の利用や処理時間を縮小し、より効率的に処理できることです。ただし、古いキャッシュを利用してしまい、情報の信頼性が下がる可能性もあります。
HTTPの重要な機能の一つにキャッシュがあります。キャッシュとは、サーバから取得したリソースをローカルストレージ(ハードディスクなど)に蓄積し、再利用する手法のことです。ローカルストレージにキャッシュしたデータそのもののこともキャッシュと呼ぶことがあります。クライアントが蓄積したキャッシュは、そのキャッシュが有効な間、クライアントが再度そのリソースにアクセスしようとしたときに再利用します。

引用: Webを支える技術 -HTTP、URI、HTML、そしてREST

同じWebサイトに複数回訪れたり、複数のページで同じ画像などを使用している場合、Webブラウザに一度読み込んだファイルはコンピュータ内のストレージに保存しておき、次に読み込むときはローカル のファイルを利用することで時間や通信資源を節約する「キャッシュ」(cache)という仕組みがある。

引用:

すごくざっくりとまとめると

  • 一度取得したデータを一時的に保存し、使い回すことができる
  • 通信回数が減ることで、通信量の削減やアプリケーションのパフォーマンス向上が期待できる
  • 古いキャッシュを使ってしまい情報が最新にならないこともある

ということが記されているかなと思います。

クライアントは、サーバーから取得したリソースを調べ、キャッシュ可能であればローカルストレージに蓄積します。

リソースがキャッシュ可能であるかどうかは、HTTPヘッダの以下の情報で判断されます。

  • Pragma
  • Expires
  • Cache-Control

キャッシュにまつわる各ヘッダの役割
Pragma

HTTP 1.0が定義したヘッダ。

キャッシュを抑制します。

Pragma は HTTP/1.0 の一般ヘッダーで、実装固有のヘッダーであり、リクエスト - レスポンスチェーンに沿ってさまざまな影響を与えます。 Cache-ControlHTTP/1.1 ヘッダーがまだ存在しない HTTP/1.0 キャッシュとの下位互換性のために使用されます。

引用:

以下のように指定することで、「この値はリソースをキャッシュしない」ということを示します。

Pragma:no-cache

これは後述するCache-Control no-cache を指定するのと意味合いは同じです。

Expires

HTTP 1.0が定義したヘッダ。

キャッシュの有効期限を示します。

Expires ヘッダーには、レスポンスが古くなると見なされる日時が入ります。

引用:

このレスポンスでは、2023年の5月11日16時(GMT)まではキャッシュが新鮮さを保つことをサーバーが保証しています。

クライアントが再度リソースにアクセスする際は、この有効期限内かどうかによって、サーバーにアクセスするか、キャッシュを利用するのかを決定します。

Cache-Control

HTTP 1.1で定義されたヘッダ。

詳細なキャッシュ方法を指定します。

前述したPragmaヘッダとExpiresヘッダはCache-Controlヘッダで完全に代用することができます。

Pragma: no-cacheの代用

Cache-Control: no-cache

Expiresでは絶対時間で有効期限を示していましたが、Cache-Controlでは現在からの相対時間で有効期限を設定可能です。

Cache-Control: max-age: 86400

こちらの例では、現在から24時間(86400秒)キャッシュが有効であることを意味します。

ブラウザ側のキャッシュ

主にGoogleChromeの仕組みに則って記述していきます。

下記を参考にさせていただきました。

おおまかに、リソースへのアクセスは以下の順序で行われていきます。

  1. InMemory Cache
  2. Service Worker Cache
  3. Browser Cache

その後、CDN→サーバーサイドへ…

順を追って、キャッシュされたリソースがなければどんどん元のデータに近づきながら問い合わせていく、という流れになります。

InMemory Cache

InMemoryとは、RAMに保存されるキャッシュのこと。

書き込み、アクセスは非常に高速ですが、RAMのデータは揮発性のため、コンピュータの電源がオフになったりすると消去されます。

ChromiumのBlinkレンダリングエンジンでは上限が8192KBと指定されています。

Service Worker Cache

Service Workerとは、ブラウザがバックグラウンドで実行するスクリプトのこと。

サービスワーカーは、基本的にウェブアプリケーション、ブラウザー、そして(もし繋がっていれば)ネットワークの間に介在するプロキシサーバーのように振る舞います。これは、よりよいオフラインの操作性を可能にするように意図されており、ネットワークのリクエストに介在してネットワークの使用可否の状況に基づいて適切な対応を取ったり、サーバー上にある資産を更新したりします。また、プッシュ通知やバックグラウンド同期の API 群へのアクセスもできるようになります。

引用:

Service Workerはfetchイベントに介入することができ、キャッシュの詳細なコントロールが可能です。

Cache Storage API、IndexedDBを用いて、リソースのキャッシュを行います。

Service Worker自体の詳細については別の記事にてまとめようと思います…。

Browser Cache

HDDやSSDなどのストレージに保存されます。

そのため、RAMを使用するInMemory Cacheよりも読み取り、書き込みに時間がかかります。

いま書いている時に撮った参考画像

画像が読み込まれない場合はページを更新してみてください。

基本的に「ブラウザのキャッシュを削除」と聞くと、Chromeなら「閲覧履歴の削除」などからキャッシュを削除する操作を思い浮かべます。

削除が必要なことからもわかるように、PCをシャットダウンしても、キャッシュされたデータは消えません。そのため、時間が経ってページを再訪した場合でもキャッシュを用いた高速なコンテンツ取得が可能となります。

まとめ

さまざまな前提をもとに、高速なWebアプリケーションを実現するために、または負荷を分散するためにどのようなキャッシュ戦略を練るのか、ということが議論されているかと思います。

キャッシュ戦略に関してはまだまだ無知なので、今回では書きませんがどこかで記事にしていけたらと思っています。

今回は以上です!!

参考