Высоконагруженный видеохостинг сократил количество запросов к базе данных для ленты на странице трендов с 4 000 в минуту до менее чем 50, а время отклика на уровне 95-го перцентиля снизил с 380 мс до 40 мс. Это стало возможным благодаря переходу от кэширования всей страницы к фрагментарному кэшированию с использованием Varnish и Edge Side Includes (ESI).

Почему сайту потребовалась другая стратегия кэширования

Главная страница, на которой отображаются самые просматриваемые ролики дня, выглядит почти одинаково для всех посетителей в регионе: около 95% HTML-кода идентичны для миллиона пользователей, в то время как остальные 5% содержат персональные данные, такие как имя вошедшего в систему пользователя или поле поиска. Инженерная команда столкнулась с двумя нежелательными вариантами:

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

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

Как была реализована фрагментарная кэшизация

Varnish, open-source HTTP-акселератор, рассматривал страницу как каркас с тремя заменяемыми частями:

  • Сетка видео — ресурсоемкий список трендовых видео для всего региона. Кэшируется на 60 секунд, так как часто меняется, но одинаков для всех анонимных посетителей.
  • Переключатель языка — статический элемент интерфейса, который меняется редко. Кэшируется на 24 часа.
  • Хедер (шапка) — единственный по-настоящему персональный фрагмент (имя пользователя, аватар, уведомления). Никогда не кэшируется; Varnish каждый раз перенаправляет запрос на сервер приложения.

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

Цифры, которые имеют значение

После перехода:

  • Нагрузка на базу данных для страницы трендов упала с 4 000 запросов в минуту до менее чем 50.
  • Задержка на уровне 95-го перцентиля снизилась с 380 мс до 40 мс.

Три практических урока внедрения

1. Grace periods сглаживают промахи кэша Когда срок действия TTL фрагмента истекает, Varnish обычно приостанавливает работу, чтобы получить свежий контент, что создает скачок задержки, который может перерасти в «эффект грохочущего стада» (thundering herd) из одновременных вызовов бэкенда. Настроив grace period (период ожидания), Varnish продолжает отдавать устаревший фрагмент, пока в фоновом режиме незаметно обновляет кэш. Пользователи не замечают пауз, а бэкенд получает стабильный, управляемый поток запросов.

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

3. Суррогатные ключи (surrogate keys) позволяют мгновенно очищать кэш Иногда видео нужно удалить немедленно — например, по соображениям авторского права. Ожидание истечения 60-секундного TTL недопустимо. Помечая каждый кэшированный фрагмент суррогатным ключом, отражающим ID соответствующих видео, команда может отправить одну команду очистки (purge), которая мгновенно аннулирует все копии конкретного видео на всех граничных узлах. Это избавляет от необходимости полной очистки кэша и помогает соблюдать правила.

Итог: Фрагментарная кэшизация с использованием Varnish и ESI превращает монолитную, зависимую от базы данных страницу в набор легковесных, многоразовых компонентов, резко снижая нагрузку на бэкенд и задержки, сохраняя при этом персонализацию для каждого пользователя.