ニクニクドットミー

カッコいいおっさんを目指すエンジニアの厳かなブログ

強いキャッシュ弱いキャッシュについて改めて調べてみた Cache-Control,Expires,Last-Modified,ETag

キャッシュについて調べることがあったのでそのメモ。強い弱いがあるのを知らなかったりCache-ControlExpiresの関係など理解ができた。やはりキャッシュは複雑だなというのが感想。

キャッシュとは?

なにかしら処理をした結果を保持しておき、その結果が必要になった場合に保持していた内容をレスポンスすることで不必要な処理を省くことができ、結果的にレスポンスを早くすることができる。
例えば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-ControlExpireが両方設定されている場合はCache-Controlが優先される。

  • shared(public)
    • 複数のクライアントから参照可能な性質を持つ。
    • 1:nでキャッシュする。本来キャッシュできないものでもキャッシュ可能。

  • private
    • 特定のクライアントのみが参照可能な性質を持つ。
    • 1:1でキャッシュする。本来キャッシュできないものでもキャッシュ可能。
    • ユーザー情報を含んだAPIなど、他者から参照されることを防ぐべき情報も含まれるので慎重に扱う

※クライアントに対してキャッシュが1:1を表す図

  • no-cache
    • オリジンサーバーに更新がないか都度確認をし、更新がなければ304ステータスになり、ローカルキャッシュを参照する。更新があればそのデータを取得する。
    • オリジンサーバーに問い合わせをしているのでリクエスト自体は発生している。
  • must-revalidate
    • no-cacheと似た挙動を持つが、キャッシュが有効期限内であればキャッシュの検証を行わないため、リクエストが発生しない。
    • 有効期限が切れている場合はキャッシュの検証を行うためリクエストを発行する。

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

    • キャッシュサイズ
      • 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の動画や音楽のキャッシュサイズ
    • データ削除ポリシー
  • 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:)