Перейти к содержанию
Innovialabs

Redis на практике: кэш, сессии, очереди и лимиты запросов

Практика3 мин

Коротко

Redis — хранилище в памяти для быстрых и недолговечных данных: кэш с TTL, сессии, лёгкие очереди, pub/sub, рейтинги и лимиты запросов, а источником истины остаётся основная база.

Для чего хорош Redis

Redis хранит данные в оперативной памяти и отвечает за микро- и миллисекунды. Поэтому он идеален для данных, которые читаются очень часто, живут недолго или должны быстро считаться. Заменой основной базе он не является: большинство данных в Redis считайте такими, которые можно потерять и восстановить.

Примеры ниже — команды redis-cli; клиентские библиотеки для Node.js, Python, Go и PHP дают те же команды.

Cache-aside с TTL

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

import json

def get_product(product_id):
    key = f"product:{product_id}"
    cached = redis.get(key)
    if cached:
        return json.loads(cached)
    product = db.fetch_product(product_id)
    redis.set(key, json.dumps(product), ex=300)  # TTL 5 минут
    return product

def update_product(product_id, data):
    db.update_product(product_id, data)
    redis.delete(f"product:{product_id}")  # инвалидация

Правила, которые спасают от багов:

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

Хранение сессий

Сессии отлично ложатся на Redis: они небольшие, читаются на каждом запросе и должны истекать.

SET session:9f2c... '{"userId":42,"role":"admin"}' EX 86400
GET session:9f2c...
EXPIRE session:9f2c... 86400   # продление при активности
DEL session:9f2c...            # выход из аккаунта

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

Простые очереди

Список работает как базовая очередь задач: продюсеры добавляют задачи, воркеры ждут их.

LPUSH queue:emails '{"to":"user@example.com","template":"welcome"}'
BRPOP queue:emails 0   # воркер ждёт, пока появится задача

Слабое место: если воркер упал, забрав задачу, она потеряна. Для надёжной обработки используйте Redis Streams с группами потребителей (XADD, XREADGROUP, XACK) или проверенную библиотеку поверх Redis — BullMQ, Sidekiq, Celery.

Pub/sub

Pub/sub рассылает сообщения всем, кто подписан в данный момент.

SUBSCRIBE orders:new
PUBLISH orders:new '{"orderId":1001}'

Сообщения не сохраняются: подписчик, который был офлайн, их пропустит. Pub/sub подходит для живых уведомлений и инвалидации кэша между серверами, Streams — когда важна доставка.

Рейтинги

Sorted set хранит элементы, упорядоченные по баллам.

ZINCRBY leaderboard:weekly 50 user:42
ZREVRANGE leaderboard:weekly 0 9 WITHSCORES   # топ-10
ZREVRANK leaderboard:weekly user:42           # место пользователя

Ограничение запросов

Счётчик с фиксированным окном — самый простой лимитер: считаем запросы по ключу за минуту.

import time

def allow(user_id, limit=60):
    key = f"rate:{user_id}:{int(time.time() // 60)}"
    count = redis.incr(key)
    if count == 1:
        redis.expire(key, 60)
    return count <= limit

Фиксированное окно допускает всплески на границах. Для более ровного лимита используйте скользящее окно на sorted set или token bucket в Lua-скрипте — так проверка и обновление выполняются атомарно.

Политики вытеснения

Когда Redis достигает maxmemory, поведение определяет настройка maxmemory-policy.

ПолитикаПоведениеКогда использовать
noevictionОтклоняет запись при заполненииОчереди, данные, которые нельзя терять
allkeys-lruУдаляет давно не использованные ключиЧистый кэш
allkeys-lfuУдаляет редко используемые ключиКэш со стабильными «горячими» ключами
volatile-lruУдаляет только ключи с TTLСмесь кэша и постоянных данных
volatile-ttlУдаляет ключи, которые скоро истекутСмешанная нагрузка со значимыми TTL

Частый подход — разные экземпляры Redis: для кэша (allkeys-lru) и для очередей или сессий (noeviction с включённой персистентностью).

Частые вопросы

Да, если персистентность выключена или между снимками. В Redis есть снимки RDB и журнал AOF — включайте их там, где данные важны, но источник истины всё равно держите в основной базе.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.