Кэширование

Сохранение готовых результатов там, откуда их можно быстро достать повторно, вместо того чтобы каждый раз вычислять или загружать заново.

Кэширование — прием, при котором результат дорогой операции сохраняют и при следующем таком же запросе отдают готовый ответ. Тяжелый отчет считается один раз в минуту, а не для каждого пользователя; картинка загружается из памяти браузера, а не из сети; страница сайта отдается готовой, а не собирается заново. Кэш — главный способ сделать систему быстрой без покупки новых серверов.

Уровни кэширования

  • Браузер хранит файлы сайта — стили, скрипты, изображения — и не скачивает их повторно. Сколько хранить, сервер подсказывает заголовком Cache-Control.
  • CDN держит копии файлов на серверах рядом с пользователями в разных городах.
  • Обратный прокси, например Nginx, может отдавать сохраненные ответы, не обращаясь к приложению.
  • Приложение сохраняет готовые страницы или результаты запросов. Этот сайт, например, хранит страницы готовыми и отдает их без повторной сборки, пока содержимое не изменится.
  • Отдельное хранилище, чаще всего Redis, общее для всех серверов приложения.
  • База данных и процессор имеют собственные кэши — в памяти СУБД и прямо внутри процессора.

Пример

Cache-Control: public, max-age=31536000, immutable

Такой заголовок говорит браузеру: файл можно хранить год и не перепроверять. Чтобы при этом пользователи получали обновления, в имя файла добавляют отпечаток содержимого (app.3f9a1c.js): изменился файл — изменилось имя, и браузер загрузит новую версию.

Главная сложность — устаревание

Известная шутка программистов: в информатике есть две трудные вещи — инвалидация кэша и придумывание названий. Кэш хорош, пока данные в нем актуальны. Подходы:

  • Время жизни (TTL) — запись живет, например, 5 минут, потом считается заново. Просто, но 5 минут пользователи могут видеть старые данные.
  • Сброс при изменении — при изменении данных соответствующие записи удаляются из кэша. Точнее, но нужно не забыть все места, где данные кэшируются.
  • Версионирование — новая версия данных получает новый ключ, а старая просто перестает запрашиваться.

Подводные камни

  • Лавина запросов. Популярная запись истекла — и сотни запросов одновременно бросаются ее пересчитывать. Помогают блокировка на пересчет и обновление заранее.
  • Персональные данные в общем кэше. Страница личного кабинета, закэшированная по ошибке для всех, — утечка. Кэшировать можно только то, что одинаково для всех, или раздельно по пользователю.
  • Память. Кэш без ограничения размера превращается в утечку памяти; нужны лимиты и политика вытеснения редко используемых записей.