キャッシュについて調べることがあったのでそのメモ。強い弱いがあるのを知らなかったりCache-Control
とExpires
の関係など理解ができた。やはりキャッシュは複雑だなというのが感想。
キャッシュとは?
なにかしら処理をした結果を保持しておき、その結果が必要になった場合に保持していた内容をレスポンスすることで不必要な処理を省くことができ、結果的にレスポンスを早くすることができる。
例えばDBから値を取得してレスポンスする場合、SQLが時間のかかるものであった場合に結果をキャッシュ(保持しておく)ことで二回目からはSQLの実行を減らすことができる。
一方、古い結果を保持し続けてしまうと新しい結果を取得できない状態になってしまうので、キャッシュする期間やキャッシュする内容は慎重に設計する必要がある。
キャッシュの種類
クエリキャッシュ
RDMS側でクエリをキャシュする。ただしMySQL8.0からは廃止され、PostgreSQLはpgpool-Ⅱを利用して実現するため、実際は使われるケースが少ない。
The query cache is deprecated as of MySQL 5.7.20, and is removed in MySQL 8.0.
https://dev.mysql.com/doc/refman/5.7/en/query-cache.html
ブラウザキャッシュ(ローカルキャッシュ)
CSS/JavaScript/画像などをブラウザでキャッシュしておき、サーバーから取得する必要がなく高速になる。
経路上のキャッシュ
Proxy/CDNを用いる、配信経路上に配置されたキャッシュ。
キャッシュでオリジンへの負荷を減らすことやクライアントに近い場所へ配置することで経路を最適化したり、大きな配信帯域を確保したりするために導入する
プロキシキャッシュ(ゲートウェイのキャッシュ)
オリジンでのキャッシュ。主にProxyを利用してキャッシュする。
Varnish,nginx,Apache Traffic Serverなど
キャッシュで利用するヘッダー
- Expire(強いキャッシュ)
- Cache-Control(強いキャッシュ)
- Last-Modified(弱いキャッシュ)
- ETag(弱いキャッシュ)
Expires
レスポンスヘッダーとしてExpires
ヘッダーに有効期限を指定することで有効期限が切れるまでは自動的にブラウザにキャッシュされたリソースを参照する。
期限が切れるまではブラウザは一度リソースを取得するとマシン内部にキャッシュするため、一度有効になるとHTTPリクエストをサーバーに送信しなくなる。
Expires: Wed, 04 Aug 2021 13:50:37 GMT
クライアントとサーバー間で時間設定が異なると、うまく設定されないケースがある。
またExpires: -1
と設定することでアクセスの1秒前の時間を設定することができるため、Cache-Control: no-cache
と組み合わせることでCache-Controle
が有効じゃないブラウザに関しても都度オリジンにリソースの検証を行うことができる。
Cache-Control
Cache-Control
を有効にすることでブラウザにキャッシュが存在する場合にはそのリソースへのリクエストが送信されないようにすることも可能(都度キャッシュが新鮮か確認させることもできる)
max-age
max-age=600
と指定した場合、取得されてから600秒間はブラウザのマシン内にキャッシュされる。
ちなみにCache-Control
とExpire
が両方設定されている場合はCache-Control
が優先される。
shared(public)
- 複数のクライアントから参照可能な性質を持つ。
- 1:nでキャッシュする。本来キャッシュできないものでもキャッシュ可能。
private
- 特定のクライアントのみが参照可能な性質を持つ。
- 1:1でキャッシュする。本来キャッシュできないものでもキャッシュ可能。
- ユーザー情報を含んだAPIなど、他者から参照されることを防ぐべき情報も含まれるので慎重に扱う
※クライアントに対してキャッシュが1:1を表す図
no-cache
- オリジンサーバーに更新がないか都度確認をし、更新がなければ
304
ステータスになり、ローカルキャッシュを参照する。更新があればそのデータを取得する。 - オリジンサーバーに問い合わせをしているのでリクエスト自体は発生している。
- オリジンサーバーに更新がないか都度確認をし、更新がなければ
must-revalidate
Last-Modified
レスポンスヘッダーにLast-Modified Wed, 18 Oct 2017 08:00:40 GMT
を設定することで次回ブラウザがリクエストを送信するときにはリクエストヘッダーにIf-Modified-Since Wed, 18 Oct 2017 08:00:40 GMT
を付与する。
If-Modified-Since
の日時とリソースの最終変更日を比較し、更新されてなければ304
ステータスを返却し、不要なデータの送信を抑えることができる。このIf-Modified-Since
を含んだGETリクエストを条件付きGETリクエストと呼ぶ。
304 Not Modified
はレスポンスボディが含まれていない小さなHTTPレスポンス。
ETag
Last-Modified
と似た挙動をするがリソースの内容が更新されているか判断をする。リソースのinode番号と更新日時とサイズからタグを生成(Apache
の例ではFileETag INode MTime Size
を仕様した場合)し、レスポンスヘッダーのETag
に設定する。
例)ETag: "30-448b28913d700"
次に同じリソースに対してリクエストを送信するときにリクエストヘッダーにIf-None-Match:"30-448b28913d700"
を設定し、サーバー側はリソースの現在のETagの値と比較し、同じであればリソースは変わってないので304
ステータスを返す。一致しない場合は対応するキャッシュがブラウザ側にないので通常のレスポンスを返す。
キャッシュの陳腐化(stale)が発生した場合の図
陳腐化したリソースへのリクエストをキャッシュが受け取るとIf-None-Match
を付加してリクエストを転送する。
https://developer.mozilla.org/ja/docs/Web/HTTP/Caching
キャッシュさせたくない場合
no-store
を指定すること
ブラウザのキャッシュサイズについて
- 永続的
- 長期間に渡って保存されるため、保存する場合はユーザーに警告ポップアップが表示される。ユーザーがデータを削除する。
一時的
- 長期間に渡って保存する必要がないデータ。ストレージの容量制限に達するとLRUポリシーに沿って削除される。
-
- キャッシュサイズ
Chrome allows the browser to use up to 80% of total disk space. An origin can use up to 60% of the total disk space.
- https://web.dev/storage-for-the-web/#how-much
-disk-cache-size
- 画像やCSSなどのキャッシュサイズ
-media-cache-seize
- HTML5の動画や音楽のキャッシュサイズ
- データ削除ポリシー
- How does eviction work?
Chromium-based browsers will begin to evict data when the browser runs out of space, clearing all site data from the least recently used origin first, then the next, until the browser is no longer over the limit.
- MRU 【Most Recently Used】
- How does eviction work?
- キャッシュサイズ
- Firefox
- キャッシュサイズ
- データ削除ポリシー
- Safari
- キャッシュサイズ
- データ削除ポリシー
Safari previously did not evict data, but recently implemented a new seven-day cap on all writable storage (see below).
Starting in iOS and iPadOS 13.4 and Safari 13.1 on macOS, there is a seven-day cap on all script writable storage, including IndexedDB, service worker registration, and the Cache API. This means Safari will evict all content from the cache after seven days of Safari use if the user does not interact with the site. This eviction policy does not apply to installed PWAs that have been added to the home screen. See Full Third-Party Cookie Blocking and More on the WebKit blog for complete details
- 書込み可能なすべてのストレージに7日間の上限が設定された模様
参考書籍
See you next time:)