Кэширование
Сохранение готовых результатов там, откуда их можно быстро достать повторно, вместо того чтобы каждый раз вычислять или загружать заново.
Кэширование — прием, при котором результат дорогой операции сохраняют и при следующем таком же запросе отдают готовый ответ. Тяжелый отчет считается один раз в минуту, а не для каждого пользователя; картинка загружается из памяти браузера, а не из сети; страница сайта отдается готовой, а не собирается заново. Кэш — главный способ сделать систему быстрой без покупки новых серверов.
Уровни кэширования
- Браузер хранит файлы сайта — стили, скрипты, изображения — и не скачивает их повторно. Сколько хранить, сервер подсказывает заголовком
Cache-Control. - CDN держит копии файлов на серверах рядом с пользователями в разных городах.
- Обратный прокси, например Nginx, может отдавать сохраненные ответы, не обращаясь к приложению.
- Приложение сохраняет готовые страницы или результаты запросов. Этот сайт, например, хранит страницы готовыми и отдает их без повторной сборки, пока содержимое не изменится.
- Отдельное хранилище, чаще всего Redis, общее для всех серверов приложения.
- База данных и процессор имеют собственные кэши — в памяти СУБД и прямо внутри процессора.
Пример: заголовок HTTP
Cache-Control: public, max-age=31536000, immutable
Такой заголовок говорит браузеру: файл можно хранить год и не перепроверять. Чтобы при этом пользователи получали обновления, в имя файла добавляют отпечаток содержимого (app.3f9a1c.js): изменился файл — изменилось имя, и браузер загрузит новую версию.
Главная сложность — устаревание
Известная шутка программистов: в информатике есть две трудные вещи — инвалидация кэша и придумывание названий. Кэш хорош, пока данные в нем актуальны. Подходы:
- Время жизни (TTL) — запись живет, например, 5 минут, потом считается заново. Просто, но 5 минут пользователи могут видеть старые данные.
- Сброс при изменении — при изменении данных соответствующие записи удаляются из кэша. Точнее, но нужно не забыть все места, где данные кэшируются.
- Версионирование — новая версия данных получает новый ключ, а старая просто перестает запрашиваться.
Подводные камни
- Лавина запросов. Популярная запись истекла — и сотни запросов одновременно бросаются ее пересчитывать. Помогают блокировка на пересчет и обновление заранее.
- Персональные данные в общем кэше. Страница личного кабинета, закэшированная по ошибке для всех, — утечка. Кэшировать можно только то, что одинаково для всех, или раздельно по пользователю.
- Память. Кэш без ограничения размера превращается в утечку памяти; нужны лимиты и политика вытеснения редко используемых записей.