[Перевод] Сила кэширования: повышаем производительность API и масштабируемость

В этой статье о том, как использовать кэширование оптимальной производительности API и веб-приложений. А также подробный обзор на методы кэширования на стороне клиента, на стороне сервера и в CDN для более быстрой и надежной работы.

5850d35af0560af1ae7acc66b73c05b8.png

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

Преимущества кэширования

  1. Повышается производительность. Кэширование позволяет избавиться от необходимости каждый раз получать данные из первоисточника. А это приводит к ускорению отклика и уменьшению задержек.

  2. Снижается нагрузка на сервер. При обслуживании кэшированного содержимого нагрузка на сервер снижается. Это позволяет ему обрабатывать больше запросов и повышает общую масштабируемость.

  3. Оптимизируется пропускная способность. Кэширование уменьшает объем данных, передаваемых по сети. За счёт этого минимизируется использование полосы пропускания и повышается эффективность.

  4. Повышается удобство работы пользователей. Более быстрое время загрузки и отзывчивость приводят к улучшению пользовательского опыта. 

  5. Снижаются затраты. Кэширование позволяет сократить вычислительные ресурсы, нужны для обработки данных. А ещё снизить затраты на инфраструктуру за счет минимизации потребности в дорогостоящих серверных ресурсах.

  6. Повышается доступность. Кэширование помогает поддерживать доступность сервиса в периоды высокой посещаемости или в случае временных сбоев в работе сервера. Это происходит за счёт обслуживания контента из кэша.

Типы кэширования

Кэширование на стороне клиента

Это процесс хранения веб-ресурсов — HTML-страниц, CSS-файлов, скриптов JavaScript и изображений — на устройстве пользователя. Как правило, в его веб-браузере. Цель кэширования на стороне клиента — ускорить загрузку веб-страниц за счёт снижения необходимости получать ресурсы с веб-сервера при каждом посещении страницы.

Когда пользователь посещает веб-сайт, его браузер делает запрос на сервер, чтобы получить нужные ресурсы. Сервер отвечает HTTP-заголовками, которые указывают браузеру, как работать с кэшированием. К таким заголовкам относятся Cache-Control, Expires, ETag (Entity Tag) и Last-Modified.

Браузер сохраняет ресурсы в своем кэше на основе правил кэширования, предоставленных сервером. При последующих запросах к той же странице или ресурсам, браузер сначала проверяет свой кэш. Если ресурс всё ещё действителен на основании заголовков кэширования, браузер извлекает его из локального кэша. Это позволяет сэкономить время и снизить  необходимость в дополнительных запросах к серверу.

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

Преимущества кэширования на стороне клиента

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

  2. Снижается нагрузка на сервер и потребление пропускной способности. Это происходит за счёт минимизации количества запросов к серверу для получения неизменных ресурсов. Оптимизация особенно важна для сайтов с высокой посещаемостью. 

  3. Улучшается пользовательский опыт и снижается число отказов. Грамотное использование кэширование помогает обеспечить бесперебойную работу браузера, оптимизировать использование ресурсов сервера и добиться более высокой общей производительности и показателей сайта.

Принцип работы кэширования на стороне клиента

В кэшировании на стороне клиента используются следующие HTTP-заголовки: Cache-Control, Expires, ETag и Last-Modified, чтобы облегчить хранение ресурсов в веб-браузерах. Когда пользователь посещает веб-сайт, эти заголовки определяют, можно ли кэшировать ресурсы и на какой промежуток времени. Браузер хранит эти ресурсы локально, а при следующих посещениях проверяет кэш на актуальность. Если ресурсы всё ещё валидны, браузер извлекает их из кэша. Это ускоряет загрузку и снижает количество запросов к серверу.

Если срок действия кэша ресурса истёк или он изменился (на основе ETag), браузер отправляет запрос на сервер. Затем сервер использует проверку кэша с помощью заголовков If-Modified-Since или If-None-Match, чтобы определить, обновлён ли ресурс. Если он не изменился, сервер отвечает статусом 304 Not Modified, и браузер продолжает использовать кэшированную версию. В противном случае он получает обновлённый ресурс для кэширования. Этот процесс обеспечивает эффективную доставку контента пользователям, сохраняя актуальность ресурсов.

Лучшие практики для кэширования на стороне клиента

Установка и настройка заголовков Cache-Control: используйте эти значения: public — для разрешения кэширования как браузерами, так и CDN, private — для кэширования только браузерами или no-cache — для повторного подтверждения ресурсов на сервере перед каждым использованием.

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

Борьба с очисткой кэша при обновлении ресурсов: при обновлении ресурсов, например CSS или JavaScript файлов, применяйте методы очистки кэша, чтобы пользователи получали последнюю версию. Например, добавление номеров версий или уникальных хэшей в URL-адреса ресурсов.

Если придерживаться этих рекомендаций, вы сможете оптимизировать кэширование на стороне клиента и повысить производительность сайта. А также снизить нагрузку на сервер и улучшить пользовательский опыт.

Проблемы кэширования на стороне клиента

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

Работа с устаревшими кэшированными ресурсами. Кэшированные ресурсы могут устаревать, особенно когда обновления происходят на стороне сервера. Это может привести к тому, что пользователи будут получать устаревшие данные. Внедрите методы проверки кэша до отправки его пользователям. Например, условные запросы с использованием заголовков ETag или Last-Modified.

Баланс между кэшированием и безопасностью. По возможности избегайте кэширования конфиденциальной информации. Если это всё же необходимо, используйте шифрование и аутентификацию. Попробуйте использовать комбинации методов кэширования на стороне клиента и на стороне сервера, чтобы найти баланс между производительностью и безопасностью.

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

Кэширование на стороне сервера

Это практика временного хранения часто запрашиваемых данных или вычислений в памяти или хранилище сервера. Основная цель — оптимизация времени отклика сервера и снижение потребности в избыточной обработке. 

Обзор механизмов серверного кэширования

Использование кэшей in-memory, таких как Redis и Memcached. Эти системы кэширования хранят данные непосредственно в RAM, обеспечивая быстрый доступ к ним. Они идеально подходят для хранения часто используемых данных, например результатов запросов к базе данных или ответов API. Из-за того, что данные хранятся в памяти, серверные приложения могут быстро получать и обслуживать кэшированный контент. Из-за этого сократится необходимость в повторных дорогостоящих запросах к базе данных или вычислениях.

Использование opcode кэшей, таких как OPcache. Это особенно актуально для веб-приложений на базе PHP. Кэши opcode хранят в памяти предварительно скомпилированный PHP-код, что избавляет от необходимости перерабатывать PHP-скрипты при каждом запросе. Это приводит к значительному повышению производительности PHP-приложений, поскольку позволяет обойтись без повторяющихся шагов парсинга и компиляции, снижая нагрузку на сервер и время отклика.

Если использовать эти механизмы кэширования, получится оптимизировать производительность сервера, минимизировать избыточные вычисления и обеспечить более быстрые и эффективные ответы на запросы клиентов. А это, в свою очередь, приведёт к улучшению пользовательского опыта и повысит отзывчивость веб-приложений.

Преимущества кэширования на стороне сервера

Снижается нагрузка на базу данных и бэкенд-часть. Благодаря кэшированию часто запрашиваемых данных в памяти, снижается необходимость в повторных запросах к базе данных и бэкенду. Сокращение объёма поиска данных и вычислений приводит к снижению нагрузки на базу данных и сервер. Это позволяет эффективно распределять ресурсы и повышает общую скорость отклика приложения.

Ускоряется время отклика на часто запрашиваемые данные. При хранении данных в кэше in-memory, например Redis или Memcached, сервер может получить и обслужить кэшированное содержимое за миллисекунды. В результате пользователи получат более быстрый отклик на часто запрашиваемые данные. А это повысит удобство работы и сократит время ожидания.

Увеличиваются возможности масштабируемости и использования преимуществ балансировки нагрузки. Снижая нагрузку на внутреннюю обработку, кэшированные данные можно быстро обслуживать, позволяя серверам обрабатывать большее количество одновременных запросов без ущерба для производительности. Это позволяет приложениям легко масштабироваться в соответствии с растущим спросом. И в то же время обеспечивать бесперебойную работу во время скачков трафика.

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

Реализация кэширования на стороне сервера

Кэширование данных на уровне приложения. Это ситуация, когда часто используемые данные хранятся непосредственно в памяти, например в массивах. Метод хорошо подходит для небольших масштабов кэширования или когда данные меняются нечасто. Однако при использовании этого подхода нужно учитывать ограничения памяти и согласованность данных.

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

Стратегия истечения срока действия и вытеснения кэша. Это нужно для того, чтобы данные в кэше оставались актуальными и не занимали лишнюю память. Истечение срока действия кэша устанавливает временной предел для кэшированных данных, после которого они считаются устаревшими и удаляются при следующем запросе. С другой стороны, политики вытеснения определяют, какие данные будут удалены, когда кэш достигнет своего предела емкости. К распространенным алгоритмам вытеснения относятся Least Recently Used (LRU) и Least Frequently Used (LFU).

При внедрении кэширования на стороне сервера разработчикам необходимо учитывать характер данных, специфические требования приложения и доступные механизмы кэширования. Это позволит эффективно оптимизировать производительность кэширования. Если комбинировать стратегии и инструменты кэширования, приложения смогут использовать преимущества серверного кэширования для ускорения времени отклика, снижения нагрузки на базу данных и более эффективного управления данными.

Оптимизация аннулирования кэша

Аннулирование кэша при серверном кэшировании гарантирует, что устаревшие данные не сохранятся в кэше. Важно внедрять методы для аннулирования кэша, чтобы поддерживать точность и согласованность данных. Есть несколько способов это сделать:

Использовать время истечения срока действия. Если установить соответствующее время истечения срока действия для кэшированных данных, кэш автоматически удаляет устаревшие записи, заставляя приложение получать свежие данные для следующего запроса.

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

Гранулярное аннулирование позволяет разработчикам выбирать конкретные записи кэша для удаления, а не очищать весь кэш. Такой подход минимизирует риск ненужного удаления из кэша часто используемых и всё ещё действительных данных. Если вы будете использовать теги кэша и гранулярное аннулирование, то сможете добиться более точного контроля над аннулированием кэша. А это приведёт к более эффективному управлению кэшем и улучшению согласованности данных.

Средства кэширования на стороне сервера

Для эффективной реализации кэширования на стороне сервера доступно несколько мощных инструментов и библиотек для кэширования. Класс Cache содержит функции для использования кэша в Toro Cloud’s Martini.

  • Guava Cache от Google — это утилита для кэширования, которая использует механизм кэширования только в памяти. Кэши, созданные этим провайдером, локальны только для одного запуска приложения (или, в данном случае, для одного запуска пакета Martini).

  • Ehcache — это полнофункциональный провайдер кэша на базе Java. Он поддерживает кэши, хранящие данные на диске или в памяти. Он также создан для масштабирования и может быть настроен для нагрузок, требующих высокого параллелизма.

  • Redis — это проект структуры данных в памяти, реализующий распределенную базу данных ключей-значений в памяти с опциональной долговечностью. Redis имеет встроенную репликацию, Lua-сценарии, LRU-вытеснение, транзакции и различные уровни стойкости на диске, а также обеспечивает высокую доступность с помощью Redis Sentinel и автоматическое разделение с помощью Redis Cluster.

Если использовать эти инструменты кэширования и интегрировать их с веб-фреймворками и CMS-платформами, получится оптимизировать время отклика сервера, сократить объем внутренней обработки и повысить общую производительность и масштабируемость своих приложений.

Функции кэширования

Интеграционные платформы корпоративного уровня часто оснащаются функциями кэширования, позволяющими хранить динамические или статические данные для их быстрого поиска. Ниже приведен пример фрагмента, демонстрирующего использование функции Cache в интеграционной платформе Martini.

Скриншот функций кэша Martini

Скриншот функций кэша Martini

Стратегии кэширования

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

Аннулирование кэша предполагает управление кэшем как на стороне клиента, так и на стороне сервера. Чтобы процесс прошёл гладко, важна согласованность на всех уровнях кэширования, тщательное планирование и реализация.

Решение проблемы согласованности кэша и эффективная обработка признания кэша недействительным позволят вам поддерживать согласованность данных во всей инфраструктуре кэширования. А также предоставить пользователям актуальный и точный контент и оптимизировать производительность.

Комбинирование методов кэширования

В гибридной стратегии кэширования используют преимущества как клиентского, так и серверного кэширования, чтобы достичь максимальной производительности и позитивного пользовательского опыта.

Используйте кэширование на стороне клиента для статических ресурсов, которые могут храниться локально в браузере пользователя. Установите соответствующие заголовки Cache-Control для определения продолжительности кэширования и оптимизируйте использование кэша браузера для ускорения загрузки при последующих посещениях.

Используйте кэширование на стороне сервера для динамического контента, который дорого генерировать при каждом запросе. Используйте кэши в памяти, например Redis или Memcached, для хранения часто используемых данных. Реализуйте стратегии истечения срока действия и вытеснения кэша, чтобы поддерживать данные в актуальном состоянии.

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

© Habrahabr.ru