Приложение растёт, и в какой-то момент обычная база данных начинает тормозить там, где раньше всё летало. Каждый заход на страницу профиля снова бьёт в Postgres, чтобы проверить, залогинен ли пользователь. Счётчик «сейчас играет N человек» пересчитывается запросом к таблице при каждом обновлении экрана. Тяжёлый отчёт, который считается несколько секунд, пользователь заказывает по десять раз подряд, потому что не видит, что уже его получал. Ни одна из этих задач не про надёжное долгое хранение — она про то, чтобы отдать ответ мгновенно и не мучить основную базу лишними запросами. Здесь и появляется Redis.
Содержание
Что такое Redis простыми словами
Redis — это база данных, которая живёт в оперативной памяти сервера, а не на диске. Отсюда и скорость: чтение из RAM в тысячи раз быстрее, чем с диска, даже с современным SSD. Postgres тоже кэширует часть данных в памяти, но всё равно устроен вокруг гарантии, что запись переживёт перезагрузку и не потеряется. У Redis приоритет обратный: сначала скорость, а надёжность хранения уже вторична и настраивается отдельно, если вообще нужна.
По структуре Redis проще, чем реляционная база. Здесь нет таблиц, схем и SQL-запросов с join'ами — есть ключи и значения. Кладёшь данные под ключом user:42:session, читаешь их обратно по тому же ключу, и это происходит за доли миллисекунды. Значением может быть не только строка — есть списки (удобно для очереди последних действий пользователя), множества (для проверки «уже голосовал ли этот человек» без дублей), отсортированные множества (готовый инструмент под таблицу лидеров с очками) и хэши — что-то вроде объекта с полями, куда удобно класть профиль пользователя целиком под одним ключом. Этого небольшого набора структур хватает для подавляющего большинства задач кэширования, без изобретения велосипеда поверх обычных строк.
Ещё одна особенность — время жизни записи. У ключа в Redis можно сразу указать TTL (time to live): например, «эта сессия живёт 24 часа», и по истечении срока Redis сам удалит запись, без отдельного фонового задания на очистку. В обычной базе такую логику пришлось бы писать самому — крон-джобом, который раз в час подчищает устаревшие строки, и следить, чтобы он не сломался незаметно.
Есть и техническая деталь, которая многое объясняет в поведении Redis: команды выполняются последовательно, одна за другой, без параллельной обработки внутри одного инстанса. Звучит как ограничение, но на практике это преимущество для сценариев вроде счётчика онлайн-игроков. Если два сервера приложения одновременно попросят увеличить один и тот же счётчик, Redis выполнит обе команды строго по очереди, и итоговое число будет верным — без гонки состояний, которая возможна при похожей операции в других системах без явной блокировки. Разработчику не нужно думать о блокировках самому, пока речь идёт об одной атомарной команде.
Зачем нужен кэш и как это ускоряет приложение
Кэш — это промежуточный слой, который хранит уже готовый результат, чтобы не считать его заново при каждом запросе. Возьмём страницу с топ-10 самых активных игроков: чтобы её построить, приложение делает запрос к базе данных с сортировкой и агрегацией по всем игрокам — операция не мгновенная, особенно если игроков десятки тысяч.
Без кэша этот тяжёлый запрос повторяется при каждом открытии страницы, хоть сто раз в минуту, хоть от одного и того же человека, который просто обновил вкладку. С кэшем всё иначе: первый запрос действительно идёт в базу и считает результат, но затем этот результат кладётся в Redis на какое-то время — скажем, на одну минуту. Все следующие обращения в течение этой минуты получают готовый ответ прямо из памяти, а основная база вообще не трогается.
Разница ощущается не только в скорости отклика, но и в нагрузке на инфраструктуру. Postgres или Supabase рассчитаны на определённое количество одновременных подключений и запросов в секунду. Каждый запрос, который перехватил кэш, — это запрос, которого база вообще не увидела. Для проекта с ограниченным тарифом это может быть разницей между «сервис держит нагрузку» и «база захлёбывается в пиковые часы».
Отдельный вопрос, который возникает сразу после того, как кэш заработал: когда обновлять устаревшие данные. Есть два простых подхода. Первый — TTL: результат живёт в кэше фиксированное время, а потом просто исчезает и пересчитывается заново при следующем запросе, без ручного вмешательства. Второй — явная инвалидация: когда данные меняются, приложение само удаляет соответствующий ключ из Redis, чтобы следующий запрос точно взял свежие данные из базы. Для таблицы лидеров обычно достаточно TTL в минуту-другую — небольшая задержка в обновлении рейтинга никого не расстроит. Для данных, где устаревание заметно и неприятно, вроде «доступен ли этот товар на складе», надёжнее явно сбрасывать кэш при каждом изменении.
Типичные кандидаты на кэширование — данные, которые часто читают и редко меняют: список популярных товаров, результаты тяжёлой аналитики, настройки приложения, публичный профиль пользователя. Плохие кандидаты — данные, которые меняются на каждый чих и должны быть свежими прямо сейчас: баланс счёта в момент оплаты, например. Кэш всегда добавляет вопрос «а не устарели ли данные», и для критичных операций этот вопрос лучше вообще не задавать, обращаясь напрямую к основной базе.
Хранение сессий пользователей
Второй классический сценарий для Redis — сессии. Когда пользователь логинится, сервер должен как-то запомнить, что именно этот браузер прошёл проверку и может видеть личный кабинет. Один из способов — хранить эту информацию на сервере под уникальным идентификатором сессии, а сам идентификатор отправить в браузер как cookie. При каждом следующем запросе браузер присылает эту cookie обратно, сервер берёт идентификатор и ищет по нему сохранённые данные — кто это, когда вошёл, какие у него права.
Хранить сессии в основной базе данных можно, но это лишняя нагрузка на систему, которая и так занята более важными вещами — заказами, платежами, постоянными данными. Сессия по своей природе временная: она живёт, пока пользователь активен, и должна исчезать сама после истечения срока или выхода из аккаунта. Это ровно та задача, под которую Redis спроектирован — записал сессию с TTL в несколько часов, и она сама испарится, когда время выйдет, без дополнительного кода на удаление.
Есть и практическая причина держать сессии отдельно от основной базы: скорость проверки авторизации напрямую влияет на отклик каждой страницы. Если сайт на каждый клик проверяет cookie через тяжёлый запрос к Postgres, отклик заметно проседает при росте аудитории. Проверка сессии в Redis — это чтение одного ключа из памяти, которое не зависит от того, сколько всего пользователей сейчас активно.
Здесь же кроется преимущество, которое особенно заметно, когда приложение растёт и начинает работать не на одном сервере, а на нескольких копиях сразу — например, для отказоустойчивости или под пиковую нагрузку. Если хранить сессию прямо в памяти процесса приложения, пользователь, чей запрос попал на второй сервер, а не на первый, где он логинился, окажется как будто не залогинен — данные о нём просто не долетели до другого процесса. Redis решает это естественно: все серверы приложения обращаются к одному общему Redis, и не важно, какой именно из них обработал конкретный запрос — сессия видна отовсюду одинаково. Именно поэтому распределённое хранилище сессий в Redis — стандартная практика и для проектов на Node.js, и для более тяжёлых серверов на Java со Spring, где готовый модуль session store поверх Redis подключается почти без ручного кода. Похожая идея — общее состояние, видимое сразу нескольким копиям сервера, — встречается и в статье про свой сервер на Socket.io: там несколько запущенных копий WebSocket-сервера синхронизируют события между собой тоже через Redis, просто задача там не про сессии, а про доставку сообщений всем подключённым клиентам.
Стоит понимать и альтернативу: не все системы хранят сессию на сервере вообще. Есть подход с JWT-токенами, где вся информация о пользователе зашита прямо в сам токен, подписанный сервером, — и серверу не нужно ничего хранить, достаточно проверить подпись при каждом запросе. У этого подхода своя цена: пока токен не истёк, отозвать его раньше срока сложно — сервер попросту не хранит список выданных токенов, чтобы вычеркнуть из него один конкретный. Хранилище сессий в Redis устроено ровно наоборот: сервер держит полный список активных сессий и может в любой момент удалить одну из них — разлогинить пользователя принудительно, например при смене пароля или подозрении на компрометацию аккаунта. За эту гибкость платишь необходимостью держать отдельное хранилище, а не только проверять подпись, — и здесь Redis подходит куда лучше, чем поход в основную базу данных на каждый запрос.
Для сравнения: в статье про базы данных для новичка разобрано, как Supabase хранит аккаунты и постоянные данные пользователей — почту, пароль, профиль. Это остаётся в Postgres и должно жить вечно, пока аккаунт существует. Сессия — совсем другое: временный пропуск, который подтверждает, что этот конкретный браузер сейчас авторизован, и который не страшно потерять, если сервер перезапустится и попросит войти заново.
Redis vs обычная база — когда что выбирать
Путаница между Redis и обычной базой данных возникает из-за того, что оба инструмента умеют «хранить данные» — но решают принципиально разные задачи. Разница не в том, какой из них лучше, а в том, для какой природы данных каждый создан.
Обычная база вроде Postgres — про надёжность. Заказ, оплата, профиль пользователя, история переписки: если эти данные потеряются, это катастрофа для бизнеса и доверия. Поэтому такая база пишет каждое изменение на диск, ведёт журналы транзакций и делает всё, чтобы данные пережили любой сбой сервера.
Redis — про скорость и временность. Данные живут в оперативной памяти, что и делает чтение с записью настолько быстрыми, но именно это и означает, что при перезапуске процесса без специальной настройки они могут исчезнуть. Для сессии или кэша это нормально: сессия истекла — пользователь просто войдёт заново; кэш пропал — приложение один раз сходит в основную базу и заново его наполнит. Ничего не сломается, просто на секунду будет чуть медленнее, чем обычно.
| Redis | Postgres / Supabase | |
|---|---|---|
| Где хранятся данные | В оперативной памяти сервера | На диске |
| Скорость чтения/записи | Очень высокая, доли миллисекунды | Ниже, зависит от запроса и индексов |
| Надёжность при перезапуске | Данные могут исчезнуть без настройки сохранения | Данные сохраняются всегда |
| Структура данных | Ключ-значение, простые структуры | Таблицы, связи, сложные запросы с join |
| Типичная задача | Кэш, сессии, счётчики, временные данные | Заказы, аккаунты, профили, всё, что нельзя терять |
| Время жизни записи | Можно задать TTL, удалится само | Хранится, пока не удалишь явно |
Практическое правило простое: если потеря этих данных прямо сейчас — проблема для пользователя или бизнеса, им место в Postgres. Если потеря — просто лёгкое неудобство, которое исправится само при следующем запросе, это кандидат для Redis. Большинство реальных приложений используют оба инструмента вместе, а не вместо друг друга: Postgres как источник правды, Redis — как ускоряющая прослойка перед ним. Ни один разработчик не выбирает «или-или» на уровне всего проекта — выбор делается для каждого конкретного вида данных отдельно.
Есть и третья группа задач, которая формально не про кэш и не про сессии, но по природе данных ближе к Redis, чем к обычной базе, — ограничение частоты запросов (rate limiting). Когда нужно не пустить пользователя отправлять больше пяти запросов к API в минуту, проще всего держать счётчик прямо в Redis с TTL в одну минуту: INCR увеличивает счётчик на каждый запрос, а по истечении минуты Redis сам обнуляет его, удалив ключ. Делать то же самое через Postgres означало бы держать отдельную таблицу с частыми обновлениями одной и той же строки под каждого пользователя — рабочий, но заметно более тяжёлый по нагрузке способ решить ту же задачу.
Поток обычно выглядит так: клиент отправляет запрос, сервер сначала проверяет, есть ли готовый ответ в Redis. Если есть — отдаёт его сразу, без похода в основную базу. Если нет — идёт за данными в Postgres, отдаёт результат клиенту и заодно кладёт его в Redis, чтобы следующий такой же запрос уже не тратил время на тяжёлый путь.
flowchart TB
A["Клиент делает запрос"] --> B["Сервер проверяет Redis"]
B -->|"есть в кэше"| C["Отдать ответ из Redis"]
B -->|"нет в кэше"| D["Запрос к Postgres"]
D --> E["Положить результат в Redis"]
E --> C
Такая схема называется cache-aside — приложение само решает, когда заглянуть в кэш, а когда пойти в базу. Это самый частый паттерн для новичка, потому что логика полностью на стороне кода и не требует специальной настройки самой базы данных.
Managed Redis vs свой сервер
Как и с Postgres в статье про базы данных, у Redis есть тот же выбор: поднимать сервер самому или взять готовый managed-сервис у облачного провайдера.
Свой сервер Redis означает установку и настройку процесса на VPS, слежение за тем, чтобы он не упал, ручную настройку сохранения на диск, если оно нужно, резервное копирование и обновление версий. Для учебного проекта это лишняя работа, которая не приближает к цели — разобраться, как кэш ускоряет приложение, а сразу превращает задачу в администрирование ещё одного сервера.
Managed Redis у облачного провайдера — сервис поднят, обновляется и мониторится провайдером, а разработчику остаётся только адрес подключения и ключ доступа. Здесь тот же принцип, что уже разбирался с Amvera для деплоя Node.js-серверов и с Supabase для Postgres: платформа берёт на себя эксплуатацию, а ты платишь деньгами по тарифу взамен на то, что не нужно администрировать инфраструктуру самому. У managed-сервисов обычно можно включить или выключить сохранение на диск отдельным переключателем, задать пароль для подключения (в облаке это почти всегда обязательно, в отличие от локального Docker-контейнера, где по умолчанию пароля может не быть вовсе) и посмотреть метрики использования памяти прямо в панели. Точные тарифы и лимиты бесплатных планов конкретных сервисов стоит смотреть прямо на их сайтах — они меняются, и приводить здесь точные цифры смысла нет.
Для локальной разработки и первого знакомства с Redis чаще всего используют Docker — официальный образ docker redis поднимает контейнер на своей машине за несколько секунд, без установки чего-либо напрямую в систему и без риска что-то сломать в основной ОС. Это удобный способ попробовать инструмент, прежде чем решать, нужен ли он в проде вообще и в каком виде — своём сервере или managed-варианте.
Отдельно стоит сказать про сетевой доступ. Локальный Redis в Docker по умолчанию открыт без пароля, потому что предполагается, что к нему обращается только код на этой же машине. В проде картина обратная: инстанс Redis не должен смотреть в открытый интернет вообще — доступ к нему настраивают либо через приватную сеть внутри облачного провайдера, либо через ограничение по IP-адресу сервера приложения, а сверху обязательно ставят пароль. Managed-сервисы обычно включают эти ограничения по умолчанию сразу при создании инстанса, а при своём сервере на VPS всё это нужно настроить руками — ещё один пункт в пользу managed-варианта, если самостоятельное администрирование не входит в цель проекта.
Ограничения и потеря данных при перезапуске
Самое важное, что нужно понять про Redis до того, как начать им пользоваться: по умолчанию данные живут только в оперативной памяти, и если процесс Redis перезапустится — из-за обновления, падения сервера или банального рестарта хостинга, — всё, что там хранилось, может исчезнуть.
Для сессий и кэша это осознанный компромисс, а не баг. Пользователи, у которых слетела сессия, просто войдут заново — раздражает, но не катастрофа. Кэш опустеет, и первые запросы после перезапуска пойдут медленнее, пока снова не наполнят его, — тоже неприятно, но не опасно, потому что источник правды, основная база, никуда не делся.
У Redis есть механизмы сохранения на диск, если устойчивость к перезапускам всё же важна. RDB делает снапшот всей памяти целиком через заданные промежутки времени — быстро восстанавливается при старте, но теряет изменения, произошедшие после последнего снапшота. AOF, наоборот, записывает в файл журнал каждой операции по мере её выполнения — потерь меньше, но сама запись чуть медленнее и файл журнала растёт быстрее. Часто используют оба механизма вместе, если для конкретных данных в Redis всё-таки важна сохранность, близкая к обычной базе. Но если для задачи важно, чтобы данные точно не потерялись никогда, это обычно сигнал, что задача не для Redis в принципе — такие данные должны с самого начала жить в Postgres или другой базе с гарантированной надёжностью, разобранной в статье про базы данных для новичка.
Второе ограничение — объём. Оперативная память сервера конечна и дороже места на диске, поэтому Redis не годится для хранения по-настоящему больших объёмов данных, только для того, что реально нужно держать под рукой прямо сейчас. Когда памяти начинает не хватать, Redis не просто падает с ошибкой — у него есть настраиваемые политики вытеснения (eviction policy): например, allkeys-lru удаляет из памяти ключи, к которым дольше всего не обращались, освобождая место под новые. Для кэша это разумное поведение по умолчанию: не критичные данные тихо уступают место более актуальным. Для сессий такую политику лучше не включать бездумно — вытесненная по нехватке памяти сессия работающего пользователя означает внезапный принудительный выход из аккаунта, и лимит памяти для инстанса, где живут сессии, стоит закладывать с запасом.
Как попробовать Redis на практике
Самый быстрый способ пощупать Redis — поднять его локально через Docker и зайти внутрь через redis cli, встроенную консольную утилиту для работы с ключами напрямую.
docker run --name my-redis -p 6379:6379 -d redis
docker exec -it my-redis redis-cli
Внутри redis cli можно поработать с базовыми командами и увидеть, как это устроено на практике:
SET user:42:name "Игорь"
GET user:42:name
SET session:abc123 "user:42" EX 3600
TTL session:abc123
INCR counter:online-players
DEL user:42:name
Команда redis set кладёт значение по ключу, GET его читает, а флаг EX 3600 в примере с сессией задаёт время жизни в секундах — через час запись исчезнет сама. TTL показывает, сколько секунд осталось жить ключу. INCR атомарно увеличивает число на единицу — удобная команда как раз для счётчика «сколько игроков сейчас онлайн», потому что несколько серверов приложения могут дёргать её одновременно, не мешая друг другу и не теряя обновления. DEL удаляет ключ вручную, когда TTL ждать не нужно.
Для данных с несколькими полями удобнее не собирать вручную JSON-строку, а взять готовую структуру-хэш:
HSET user:42 name "Игорь" level 7 online true
HGETALL user:42
HGET user:42 level
HSET кладёт сразу несколько пар «поле-значение» под одним ключом, HGETALL забирает всё целиком, а HGET — только конкретное поле, не читая остальные. Для профиля пользователя в кэше это удобнее плоских строковых ключей вроде user:42:name, user:42:level по отдельности: меньше ключей, один TTL на всю запись, и не нужно собирать и разбирать текстовый формат самому.
Для реального приложения Redis обычно подключают не через консоль, а через библиотеку на языке, на котором написан сервер. Например, для Node.js есть пакет ioredis или официальный клиент redis, а для питона есть библиотека redis python, у которой синтаксис методов почти дословно повторяет команды консоли:
import redis
r = redis.Redis(host="localhost", port=6379, decode_responses=True)
r.set("user:42:name", "Игорь")
r.setex("session:abc123", 3600, "user:42")
print(r.get("user:42:name"))
Если сервер приложения написан на Java со Spring, там своя экосистема: spring redis через модуль Spring Data Redis даёт готовую абстракцию поверх тех же команд, с аннотациями для кэширования методов почти без ручного кода — достаточно пометить метод, и результат его вызова сам ляжет в Redis и подхватится оттуда при повторном обращении с теми же параметрами.
При первом подключении почти неизбежно встретится redis error — обычно это одна из трёх причин. Либо сервер попросту не запущен и порт недоступен, либо в строке подключения опечатка в адресе или порте, либо истёк лимит памяти на бесплатном managed-плане, и запись отклоняется. В логе клиента обычно явно написано, какая из трёх причин сработала, и это первое место, куда стоит смотреть при отладке, прежде чем менять код.
Прежде чем просить ИИ-ассистента подключить Redis к своему проекту, полезно понимать, что именно ты просишь: не «замени базу данных», а «добавь промежуточный слой кэша перед существующей базой» — так ассистент не станет переносить туда данные, которые должны храниться постоянно.
Частые вопросы
Redis заменяет обычную базу данных?
Нет, и не должен. Redis дополняет базу данных, ускоряя доступ к часто запрашиваемым или временным данным, но постоянное хранение — заказы, аккаунты, любые данные, потеря которых недопустима, — остаётся за Postgres или Supabase.
Что будет с данными в Redis, если сервер перезагрузится?
По умолчанию данные в памяти исчезнут. Для сессий и кэша это нормально: пользователь войдёт заново, кэш наполнится при следующих запросах. Если нужна устойчивость к перезапускам, включают сохранение на диск через RDB или AOF, но это уже отдельная настройка, а не поведение по умолчанию.
Нужен ли Redis для маленького учебного проекта?
Обычно нет. Пока трафика немного и запросы к базе не создают заметной задержки, добавлять ещё один сервис в инфраструктуру — лишняя сложность. Redis имеет смысл подключать, когда конкретный запрос реально стал узким местом, а не заранее «на будущее».
Чем Redis отличается от простого кэширования в памяти самого приложения?
Кэш внутри процесса приложения (например, обычный словарь в памяти Node.js-сервера) живёт только на одном сервере и пропадает при перезапуске процесса. Redis — отдельный сервис, к которому могут обращаться сразу несколько серверов приложения одновременно, поэтому он подходит, когда приложение масштабируется на несколько инстансов и всем нужен общий кэш или общее хранилище сессий.
Можно ли хранить в Redis данные, которые нельзя терять?
Технически можно включить сохранение на диск и снизить риск потери, но это не то, для чего Redis спроектирован в первую очередь. Если данные критичны, надёжнее держать их в базе, которая изначально построена вокруг гарантии сохранности, как Postgres.
Что произойдёт, если Redis закончится оперативная память?
Зависит от настроенной политики вытеснения. При включённом allkeys-lru и похожих режимах Redis сам освобождает место, удаляя давно не запрошенные ключи, — новые записи проходят, старые тихо теряются. Если политика вытеснения не настроена, новые записи вместо этого начнут отклоняться с ошибкой при достижении лимита памяти. Для кэша первый вариант обычно безопаснее, для чувствительных данных лимит памяти стоит заранее закладывать с запасом.
Можно ли использовать Redis для ограничения частоты запросов к API?
Да, это одна из типичных задач для него наравне с кэшем и сессиями. Счётчик запросов на пользователя с коротким TTL решает rate limiting проще и с меньшей нагрузкой на инфраструктуру, чем аналогичная логика через таблицу в основной базе данных.
Сложно ли подключить Redis к своему приложению?
Не сложнее, чем подключить любую другую базу данных: нужен адрес сервера, порт и обычно пароль, а дальше работа идёт через клиентскую библиотеку на языке проекта. Основная сложность не в самом подключении, а в том, чтобы решить, какие именно данные стоит кэшировать и на какое время.
Заключение
Redis решает узкую, но частую задачу: отдать данные мгновенно там, где обычная база начинает быть избыточно медленной или неудобной для того, что и так должно жить недолго. Кэш экономит обращения к основной базе, а хранение сессий снимает с постоянного хранилища лишнюю нагрузку от проверки авторизации на каждый клик — и заодно решает проблему, когда приложение работает сразу на нескольких серверах.
Здесь же граница инструмента: Redis не заменяет Postgres или Supabase, а работает рядом с ними — как быстрая прослойка перед медленным, но надёжным хранилищем. Разделение простое: то, что нельзя терять, остаётся в обычной базе; то, что можно быстро восстановить или что и так временно по своей природе, переезжает в Redis. Если в проекте появляются данные, которые часто читают, редко меняют и не страшно на секунду потерять, — это и есть сигнал, что настало время попробовать Redis.
Начать проще всего с локального контейнера через Docker: подключить его к уже работающему приложению, вынести туда один конкретный тяжёлый запрос или проверку сессии, и сравнить отклик до и после. Этого небольшого эксперимента обычно достаточно, чтобы почувствовать разницу и решить, стоит ли переносить в Redis что-то ещё.
Читай дальше
Все статьиНе просто статьи — тебя доведут до результата
В практикуме за 2499 ₽ рядом живая команда практикующих разработчиков и маркетологов: ведём по шагам до твоего работающего приложения. Не «ролики и сам разбирайся» — помогаем на каждом затыке.
Перейти к практикуму