Пользователь заходит на сайт. Браузер отправляет запрос на сервер. Сервер идёт в базу данных, собирает данные, рендерит HTML, отправляет обратно. На всё это уходит 1–3 секунды. Если каждый запрос делает всё это заново — сайт будет медленным независимо от мощности сервера.
Кэширование — это сохранение результата, чтобы при следующем запросе не делать работу заново. Первый запрос: 1,5 секунды. Второй: 50 миллисекунд. Тысячный: те же 50 миллисекунд. Это и есть «ускорение в 10–30 раз».
Разбираем 5 уровней кэширования — от браузера пользователя до базы данных. Для каждого: что кэшировать, как настраивать, какие ошибки допускают. С конкретными примерами и цифрами.
1. Пять уровней кэширования
Кэш — это не одна система, а слои. Каждый следующий ловит то, что не поймал предыдущий. Настроив все пять, вы получаете максимальную скорость.
Статика (CSS, JS, картинки, шрифты) сохраняется в браузере пользователя. При повторных заходах загружается с диска — 0 запросов к серверу.
Раздаётся через сеть серверов по всему миру. Пользователь из Владивостока получает картинку с сервера во Владивостоке, а не с вашего сервера в Москве.
HTML-страницы, результаты сложных вычислений, ответы API сохраняются в Redis или в памяти. Не надо рендерить страницу каждый раз.
Результаты частых SQL-запросов сохраняются отдельно. Или используются материализованные представления для тяжёлых агрегатов.
Файловый кэш ОС и кэш процессора — работают автоматически, ничего настраивать не нужно, но понимать полезно.
Для большинства сайтов первые три уровня дают 90% ускорения. Начните с них, потом переходите к четвёртому, если сайт сильно нагружен.
2. HTTP-кэш: самый дешёвый уровень
HTTP-кэш работает через заголовки ответа. Когда сервер отдаёт файл, он добавляет заголовки, которые говорят браузеру: «этот файл можно сохранить и не перезапрашивать вот столько времени».
Основные заголовки:
# Файл можно кэшировать на 1 год
Cache-Control: public, max-age=31536000, immutable
# Файл можно кэшировать на 1 час
Cache-Control: public, max-age=3600
# Кэш только у клиента, не в CDN
Cache-Control: private, max-age=300
# Не кэшировать (для админки, личного кабинета)
Cache-Control: no-store, must-revalidate
Правильная стратегия: «вечные» файлы получают хеш в имени: app.abc123.css. Тогда их можно кэшировать на год через immutable. Когда файл меняется — меняется и хеш, браузер скачивает новую версию.
HTML-страницы кэшируются иначе — на короткое время или с проверкой через ETag и Last-Modified. Браузер отправляет серверу «у меня есть версия с таким ETag», сервер отвечает «304 Not Modified» без тела страницы. Это экономит трафик и время.
Кэшировать HTML-страницы без версионирования. Если страница «О компании» меняется, а браузер всё ещё показывает старую версию — пользователь думает, что вы не обновляете сайт. Для HTML используйте короткий max-age (5–15 минут) или no-cache с обязательной проверкой через ETag.
3. CDN: раздача статики по всему миру
Если ваш сервер стоит в Москве, а пользователь заходит из Новосибирска, запрос идёт через всю страну. Задержка — 100+ миллисекунд на каждый файл. Загрузить сайт с 50 файлами = 5 секунд только на задержках.
CDN решает это: файлы раздаются с ближайшего к пользователю сервера. Из Новосибирска — с сервера в Новосибирске. Из Владивостока — с сервера во Владивостоке. Задержка падает до 5–20 миллисекунд.
Что отдавать через CDN:
- Изображения, иконки, логотипы
- CSS и JavaScript
- Шрифты
- Видео и аудио
- Статические HTML-страницы (если сайт на SSG)
Что выбрать: Cloudflare — бесплатный тариф покрывает потребности большинства сайтов. Даёт кэш, защиту от DDoS, SSL, оптимизацию картинок. Российские аналоги — Selectel CDN, Gcore. Для российского бизнеса лучше российские (152-ФЗ и скорость).
4. Кэш приложения: Redis и память
Здесь начинается самое интересное. HTML-страница, которую генерирует ваш код, — это результат работы десятков SQL-запросов и шаблонизатора. Если страница одна и та же для всех — зачем генерировать её заново каждый раз?
Простой пример на Python (Django):
from django.core.cache import cache
def get_article(slug):
# Пробуем взять из кэша
cached = cache.get(f'article:{slug}')
if cached:
return cached
# Если нет — идём в БД
article = Article.objects.get(slug=slug, status='published')
# Сохраняем в кэш на 10 минут
cache.set(f'article:{slug}', article, timeout=600)
return article
Первый запрос: 250 миллисекунд (SQL + рендер). Второй и последующие: 2–5 миллисекунд (запрос к Redis).
Redis или Memcached?
- Redis — умеет больше: списки, множества, публикация/подписка. Может работать и как кэш, и как очередь задач, и как хранилище сессий. Выбор по умолчанию в 2026.
- Memcached — проще, легче, чуть быстрее на чистом кэше. Но больше ни для чего не подходит.
Для сайта с 100–1000 посетителей в день хватает Redis на самом слабом VPS (128 МБ памяти). Для высоконагруженного проекта — Redis-кластер или managed-решение.
Что кэшировать: результаты тяжёлых SQL-запросов, HTML-фрагменты (меню, футер, блоки «популярное»), ответы внешних API, результаты сложных вычислений. Что НЕ кэшировать: корзину, личный кабинет, всё, что зависит от конкретного пользователя.
5. Кэш базы данных
Даже с кэшем приложения часть запросов всё равно идёт в базу. Это нормально — но некоторые запросы настолько часты, что их тоже стоит кэшировать.
Три подхода:
- Индексы. Не совсем кэш, но эффект похож. Правильный индекс превращает запрос по таблице из 100 000 строк из 500 мс в 5 мс. Это самое дешёвое ускорение — просто добавьте индекс.
- Материализованные представления. Если у вас есть запрос «топ-10 товаров за месяц» — он выполняется каждый раз. Материализованное представление сохраняет результат, обновляется по расписанию.
- Query cache. Некоторые СУБД (MySQL) кэшируют результаты одинаковых запросов. Устаревший механизм, в новых версиях его убрали — лучше использовать Redis.
Пример материализованного представления (PostgreSQL):
CREATE MATERIALIZED VIEW popular_products AS
SELECT
p.id,
p.name,
COUNT(o.id) AS order_count
FROM products p
JOIN orders o ON o.product_id = p.id
WHERE o.created_at > now() - interval '30 days'
GROUP BY p.id, p.name
ORDER BY order_count DESC
LIMIT 10;
-- Обновляем раз в час
REFRESH MATERIALIZED VIEW CONCURRENTLY popular_products;
Цифры: запрос «топ-10 за месяц» по таблице orders с 1 миллионом строк занимает 1,8 секунды. Из материализованного представления — 3 миллисекунды. Ускорение в 600 раз.
6. Инвалидация кэша: самая сложная часть
«В информатике есть только две сложные вещи: инвалидация кэша и придумывание имён». Фил Карлтон, 1996 год. С тех пор ничего не изменилось.
Проблема: как понять, что кэш устарел? Если вы закэшировали страницу товара, а потом поменяли цену — старый кэш продолжит показывать старую цену. Это хуже, чем медленный сайт.
Три стратегии:
- По времени (TTL). Кэш живёт фиксированное время: 5 минут, час, сутки. Просто и понятно, но не всегда точно. Для товаров с редко меняющейся ценой — подходит. Для акции «скидка до конца дня» — плохо.
- По событию. При изменении данных явно удаляем кэш. Например, обновили цену товара — сбросили кэш страницы этого товара. Точно, но нужно не забыть сбросить везде, где нужно.
- По версии. Добавляем к ключу версию данных. Изменилась — ключ тоже изменился. Это самый гибкий способ, особенно для CDN-кэша.
Если вы показываете устаревшие цены, недоступные товары или неправильные данные — пользователи перестают доверять сайту. Лучше чуть медленнее, но всегда актуально, чем быстро с устаревшими данными. Начинайте с коротких TTL и постепенно увеличивайте.
7. Что категорически нельзя кэшировать
- Личный кабинет. Каждый пользователь должен видеть только свои данные. Если случайно закэшировать чужую страницу — утечка данных и огромные проблемы.
- Корзину. Корзина привязана к сессии. Если два пользователя увидят одну корзину — потеряете обоих.
- Админку. Кэширование админки — верный способ запутаться самому. Обязательно
Cache-Control: no-store. - Формы и токены. CSRF-токены, каптчи, одноразовые ссылки должны быть уникальными для каждого запроса.
- Страницы акций с таймером. Если у вас «до конца акции 2 часа», кэш на час покажет неправильное время.
Кэширование — самое дешёвое ускорение сайта. Не нужно покупать мощный сервер или переписывать код. Достаточно правильно расставить заголовки и настроить Redis. Сайт, который грузился 3 секунды, будет грузиться 300 миллисекунд — и конверсия вырастет на 20–30%.
Ускорим ваш сайт
Настроим кэширование на всех уровнях: HTTP, CDN, Redis, БД. Проведём замеры до и после. От 15 000 ₽.