PRO

Как использовать Redis для хранения сессий и ограничения частоты запросов?

Redis подходит для хранения сессий и ограничения частоты запросов благодаря быстрому доступу по ключу и TTL. Сессию сохраняют по случайному идентификатору со сроком жизни, а для простого лимита запросов используют атомарный счётчик и время истечения ключа.
Подробный ответ

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

После входа пользователя приложение создаёт случайный идентификатор сессии, сохраняет в Redis связанные данные и отправляет идентификатор клиенту в защищённой cookie. При каждом запросе приложение по идентификатору получает сессию из Redis.

session_id = create_secure_random_token()

redis_client.hset(
    f'session:{session_id}',
    mapping={
        'user_id': user.id,
        'role': user.role,
    },
)
redis_client.expire(f'session:{session_id}', 3600)

Продление сессии

При активном использовании можно обновлять TTL сессии. Это называют скользящим сроком жизни: сессия продлевается после успешного запроса, но истекает при долгой неактивности.

redis_client.expire(f'session:{session_id}', 3600)

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

Простой вариант использует ключ на пользователя или IP-адрес и счётчик запросов за фиксированный интервал. Redis выполняет увеличение счётчика атомарно.

def allow_request(client_id: str, limit: int = 100) -> bool:
    key = f'ratelimit:{client_id}:minute'
    current = redis_client.incr(key)

    if current == 1:
        redis_client.expire(key, 60)

    return current <= limit

Если за минуту число запросов превысит limit, API возвращает 429 Too Many Requests.

Недостаток фиксированного интервала

Фиксированный интервал допускает всплеск на границе минут. Пользователь может отправить 100 запросов в конце одной минуты и ещё 100 в начале следующей. Для более точного ограничения используют скользящий интервал или алгоритм «ведро с токенами».

Распределённая система

Redis должен быть общим для всех экземпляров API. Если каждый сервер считает запросы только в собственной памяти, клиент сможет обойти лимит, попадая на разные реплики. Для сложного алгоритма несколько действий Redis объединяют в Lua-скрипт, чтобы выполнить их атомарно.

Безопасность сессий

  • идентификатор сессии должен быть криптографически случайным;

  • cookie должна иметь флаги HttpOnly, Secure и подходящий SameSite;

  • сессию нужно удалять при выходе и при смене пароля;

  • не следует хранить в сессии больше данных, чем действительно нужно.

Как ответить на собеседовании

Для сессий храню в Redis данные по случайному идентификатору с TTL, а клиент получает только идентификатор в защищённой cookie. Для ограничения частоты использую общий Redis, атомарный INCR и EXPIRE. При высокой нагрузке выбираю ключ по пользователю или API-ключу, а для точного распределённого алгоритма использую атомарный Lua-скрипт или отдельный компонент ограничения запросов.

Оцени свой прогресс

Честно оцени своё понимание этого вопроса, чтобы мы могли построить твой учебный трек максимально эффективно.
Читать в блоге