Задача о кешировании - Академия Selectel

Задача о кешировании

Артём Шумейко
Артём Шумейко Senior Python Backend-разработчик
24 марта 2025

Задача будет полезна разработчикам, которым любопытно, как сделать приложение быстрее.

Изображение записи

Текст подготовил Артём Шумейко — внештатный райтер, амбассадор Selectel и автор YouTube-канала о разработке.

Условие

Фулстек-разработчик Тимур Рэксов устроился в компанию «СуперСофт». Молодой человек отвечает за скорость и масштабирование основного веб-сервиса.

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

  • Расширенная аналитика: специальная страница, на которой сотрудники формируют отчеты по продажам, используя сложные фильтры и агрегации. Эта страница генерирует множество «тяжелых» SQL-запросов, из-за чего в пиковые моменты база проседает по производительности.
  • Поиск с автоподсказками: пользователи начинают вводить название товара, и система должна мгновенно выдать список подходящих вариантов. Когда трафик высок, сервер получает много таких запросов, поскольку автоподсказки «срабатывают» при каждом новом символе.
  • Персональные настройки интерфейса: после авторизации пользователь может выбирать светлую или темную тему, задавать язык интерфейса, а также сохранять виджет «рекомендуемые товары». Проблема в том, что при каждой перезагрузке страницы такие настройки приходится заново подтягивать с бэкенда. Это приводит к дополнительным задержкам, особенно при большом количестве пользователей.

Тимлид хочет, чтобы все эти фичи работали быстрее, а база не «роняли» базу.

Задача

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

Решение

В современных веб-приложениях существует множество уровней, на которых можно внедрять кеширование. Где-то достаточно выставить корректные заголовки Cache-Control в веб-сервере, а где-то эффективнее использовать механизмы Materialized View в базе данных PostgreSQL или in-memory-решения наподобие Redis. Иногда достаточно сохранять пользовательские данные в localStorage, чтобы избавить бэкенд от лишних запросов. Каждый способ кэширования хорош в своей ситуации и зависит от того, как часто обновляются данные, насколько важна их актуальность и какова интенсивность запросов.

Расширенная аналитика. Чтобы ускорить формирование аналитики, можно частично переложить вычислительную нагрузку с онлайновых запросов на заранее подготовленные материализованные представления. Суть в том, что сложные агрегации не исполняются при каждом запросе к базе, а только один раз рассчитываются и сохраняются в специальной таблице. Такой подход особенно полезен, когда отчеты требуют множественных JOIN’ов и фильтраций по большим объемам данных.

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

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

Поиск с автоподсказками. Вторая фича требует иного подхода. Здесь запросы небольшие по объему, но происходят часто, поскольку автокомплит срабатывает при каждом новом символе в строке поиска. Если отправлять все эти запросы напрямую в базу, то при высокой посещаемости сервиса нагрузка на СУБД может стать критичной. В такой ситуации in-memory решение вроде Redis хорошо справляется с частыми операциями чтения и обновления. Там можно хранить часто запрашиваемые варианты автоподсказок или даже часть индекса для быстрого поиска по префиксам. 

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

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

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

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

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

Больше задач для программистов