Как правильно кешировать запросы в Node.js REST API чтобы не положить базу
Рейтинг: 65.9% · 59 голосов
Войдите, чтобы голосовать
Голосовать «За» и «Против» могут только авторизованные пользователи. Войдите в свой аккаунт — или зарегистрируйтесь, это займёт минуту.
Нет аккаунта? Зарегистрироваться
- asynclover
- Сообщения: 70
- Зарегистрирован: 13 май 2026, 04:35
Как правильно кешировать запросы в Node.js REST API чтобы не положить базу
Проблема: REST API на Node.js + Express + PostgreSQL. Один эндпоинт — тяжёлая аналитическая выборка, иногда до 3 секунд. Пользователей немного (~200 одновременно), но они долбят этот эндпоинт часто, у некоторых страница перезагружается каждые 30 секунд. База начинает задыхаться. Пробовал добавить Redis, но не понимаю правильную стратегию — когда инвалидировать кеш, как не отдавать протухшие данные.
✔ Лучший ответ выбран автором темы — matguyvr
Для аналитических запросов с допустимой задержкой данных (а 30-секундный polling это явно допустимая задержка) — TTL-кеш в Redis это правильное решение. Ставишь TTL равным тому периоду за который данные допустимо устаревают. Если данные обновляются раз в 5 минут — TTL 5 минут. Простая схема: hit кеша — отдаёшь из Redis, miss — идёшь в базу, пишешь в Redis, отдаёшь клиенту. Сотни параллельных…
✔ Лучший ответ сформирован автоматически — Vthors22
Если у тебя один инстанс Node, не торопись городить distributed lock — сначала сделай дедупликацию на уровне процесса. Держишь Map: пришёл запрос, кеш пустой — кладёшь промис запроса к базе в мапу, все параллельные запросы с тем же ключом ждут этот же промис, по завершении пишешь в Redis и чистишь мапу. Двадцать строк кода, и при истечении TTL в базу уходит ровно один запрос вместо…
Re: Как правильно кешировать запросы в Node.js REST API чтобы не положить базу
✔ Лучший ответ — выбран автором
Для аналитических запросов с допустимой задержкой данных (а 30-секундный polling это явно допустимая задержка) — TTL-кеш в Redis это правильное решение. Ставишь TTL равным тому периоду за который данные допустимо устаревают. Если данные обновляются раз в 5 минут — TTL 5 минут. Простая схема: hit кеша — отдаёшь из Redis, miss — идёшь в базу, пишешь в Redis, отдаёшь клиенту. Сотни параллельных запросов превращаются в один запрос к БД каждые N минут.
Re: Как правильно кешировать запросы в Node.js REST API чтобы не положить базу
Есть нюанс который называется cache stampede — когда TTL истекает и 50 запросов одновременно идут в базу. Решается через lock или через паттерн stale-while-revalidate: отдаёшь устаревшие данные сразу, в фоне обновляешь кеш. В node.js можно реализовать через simple-lru-cache или через Redis SET NX для distributed lock. Для 200 пользователей это не критично, но знать полезно.
Re: Как правильно кешировать запросы в Node.js REST API чтобы не положить базу
Смотрел на твою схему — polling каждые 30 секунд это само по себе антипаттерн если данные меняются редко. Рассмотри Server-Sent Events или WebSocket с push-уведомлениями только при изменении данных. Меньше нагрузки, более актуальные данные, меньше головной боли с кешем. Node.js для этого отлично подходит.
Re: Как правильно кешировать запросы в Node.js REST API чтобы не положить базу
Конкретная реализация для Express + Redis (ioredis): пишешь middleware который по ключу (url + query params) проверяет Redis, если есть — res.json(cached), если нет — next() и в конце обработчика вызываешь redis.setex(key, ttlSeconds, JSON.stringify(result)). Ключ кеша важно делать детерминированным, иначе один и тот же логический запрос будет разными ключами. Ещё момент: не забудь что Redis хранит строки, JSON.parse/stringify обязателен.
Re: Как правильно кешировать запросы в Node.js REST API чтобы не положить базу
А ещё посмотри на сам запрос — 3 секунды это очень долго. EXPLAIN ANALYZE в Postgres покажет где узкое место. Скорее всего не хватает индексов или нет материализованного представления для агрегатов. Кеш это хорошо, но если запрос можно ускорить до 100ms — часть проблемы уйдёт сама.
Re: Как правильно кешировать запросы в Node.js REST API чтобы не положить базу
✔ Лучший ответ — сформирован автоматически
Если у тебя один инстанс Node, не торопись городить distributed lock — сначала сделай дедупликацию на уровне процесса. Держишь Map<key, Promise>: пришёл запрос, кеш пустой — кладёшь промис запроса к базе в мапу, все параллельные запросы с тем же ключом ждут этот же промис, по завершении пишешь в Redis и чистишь мапу. Двадцать строк кода, и при истечении TTL в базу уходит ровно один запрос вместо пятидесяти. Для 200 пользователей этого хватит с огромным запасом, а Redis SET NX оставь на момент, когда инстансов станет несколько.
Re: Как правильно кешировать запросы в Node.js REST API чтобы не положить базу
@js066866, плюсую и доведу мысль до конца: если выборка агрегатная, материализованное представление с REFRESH MATERIALIZED VIEW CONCURRENTLY по крону раз в N минут может заменить Redis целиком. Эндпоинт читает из matview за миллисекунды, проблема инвалидации исчезает как класс — свежесть данных задаётся расписанием рефреша, и это честный ответ на вопрос ТС «когда инвалидировать». Минус одна движущаяся часть в инфраструктуре, и не надо думать про сериализацию и протухшие ключи.
Re: Как правильно кешировать запросы в Node.js REST API чтобы не положить базу
@TcpAdmin, SSE — красиво, но для 200 юзеров это пушка по воробьям: держать соединения, разруливать реконнекты, таймауты прокси и балансировщика, fallback для тех, у кого корпоративный файрвол режет долгие коннекты. Я бы сначала довёл до ума сам polling: ETag плюс Cache-Control max-age=30 на эндпоинте — и заметная часть перезагрузок вообще не долетит до сервера, браузер сам отдаст 304. Если после этого упрутся в актуальность данных — вот тогда SSE оправдан, но не как первый шаг.
Поделиться темой:
✈ Telegram
VK
- Похожие темы
-
-
- useEffect и массив зависимостей — линтер требует положить функцию, кладу — бесконечный цикл
13 ответов · 346 просмотров
-
-
-
-
- vLLM в проде падает с OOM при всплесках трафика — как правильно настроить KV-cache и batching?
8 ответов · 85 просмотров
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость