JavaRush /Курсы /Модуль 4: FastAPI /Пример использования Redis для кэширования частых запросо...

Пример использования Redis для кэширования частых запросов

Модуль 4: FastAPI
9 уровень , 4 лекция
Открыта

Кэширование частых запросов — это, грубо говоря, как использование памяти "Ctrl+C" и "Ctrl+V". Вы берёте часто запрашиваемую информацию, сохраняете её в более лёгкодоступном месте и используете её, не прибегая каждый раз к тяжелым механизмам получения данных. Частые запросы, особенно к базе данных, могут значительно замедлить приложение. Кэширование решает эту проблему:

  • Экономия ресурсов: данные извлекаются из памяти (Redis), а не базы данных.
  • Снижение нагрузки на базу данных: уменьшение числа запросов к базе, что особенно важно для высоких нагрузок.
  • Ускорение ответов: в большинстве случаев читать из Redis быстрее, чем из базы данных.
  • Улучшение пользовательского опыта: никто не любит ждать.

Как выбрать, что кэшировать?

Не всё, что движется (или, в нашем случае, запрашивается), нужно кэшировать. Вот несколько советов для выбора:

  1. Частота запроса: если запрос выполняется часто, это первый кандидат для кэширования.
  2. Стабильность данных: данные, которые редко изменяются (например, курсы валют), идеально подходят для кэширования.
  3. Время выполнения запроса: если запрос медленный, его результаты стоит кэшировать, чтобы не "морозить" приложение.

Хорошие кандидаты для кэширования — это поисковые результаты, статистика, метаданные и т.п.


Реализация кэширования частых запросов в FastAPI

Давайте разберём, как кэшировать частые запросы к базе данных с использованием Redis.

Шаг 1: настройка Redis в FastAPI


from fastapi import FastAPI, Depends
import redis
import hashlib

# Настройка FastAPI
app = FastAPI()

# Настройка подключения к Redis
redis_client = redis.StrictRedis(host='localhost', port=6379, decode_responses=True)

Маленький совет: чтобы не терять голову, проверяйте, что Redis-сервер запущен. Если он не запущен, FastAPI будет выглядеть как потерянный ребенок без своей любимой игрушки.

Шаг 2: пример хранилища данных

Допустим, у нас есть фейковая база данных со списком пользователей:


FAKE_DB = {
    1: {"id": 1, "name": "John Doe", "email": "john.doe@example.com"},
    2: {"id": 2, "name": "Jane Smith", "email": "jane.smith@example.com"},
    3: {"id": 3, "name": "Alice Johnson", "email": "alice.johnson@example.com"}
}

Шаг 3: хэширование ключей для Redis

Чтобы запросы к кэшу были уникальны и предсказуемы, удобно использовать хэш в качестве ключей. Например:


def make_cache_key(function_name: str, *args):
    key = f"{function_name}:{':'.join(map(str, args))}"
    hashed_key = hashlib.sha256(key.encode()).hexdigest()
    return hashed_key

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

Шаг 4: реализация кэширования данных

Теперь мы кэшируем запросы. Первым делом проверим, есть ли данные в кэше. Если да — вернём их. Если нет — возьмём из базы данных, сохраним в Redis и вернём клиенту.


@app.get("/users/{user_id}")
def get_user(user_id: int):
    cache_key = make_cache_key("get_user", user_id)
    
    # Проверяем кэш
    cached_user = redis_client.get(cache_key)
    if cached_user:
        print("Получено из кэша")
        return eval(cached_user)  # Оценка строки в Python (осторожно!)

    # Если в кэше нет, получаем из "базы"
    user = FAKE_DB.get(user_id)
    if user:
        # Сохраняем данные в Redis с TTL 30 секунд
        redis_client.setex(cache_key, 30, str(user))
    return user

Шаг 5: тестирование

  1. Запустите приложение.
  2. В браузере или с помощью cURL откройте следующий URL: http://127.0.0.1:8000/users/1.
  3. Проверьте логи. Если всё работает как нужно, на первый запрос вы увидите Получено из базы, а на последующие — Получено из кэша.

Инвалидирование данных

Данные в кэше могут устареть. Например, информация о пользователе изменилась, но в кэше мы всё ещё возвращаем старую копию.

Принципы инвалидирования:

  1. TTL: устанавливайте короткое время жизни (setex), чтобы данные автоматически удалялись из кэша.
  2. Ручная очистка: удаляйте кэшированные данные, если они изменились.
  3. Уникальность ключей: изменяйте ключи для новых данных.

Пример удаления устаревшего кэша:

Допустим, мы обновляем email пользователя. После обновления очистим его кэш:


@app.put("/users/{user_id}")
def update_user(user_id: int, email: str):
    user = FAKE_DB.get(user_id)
    if user:
        user["email"] = email
        
        # Инвалидируем кэш
        cache_key = make_cache_key("get_user", user_id)
        redis_client.delete(cache_key)
        return {"msg": "User updated successfully"}
    return {"msg": "User not found"}

Зачем это нужно в реальной жизни?

Представьте, у вас есть крупный e-commerce сайт. Запросы на главную страницу, фильтры и страницы товаров составляют 90% нагрузки на базу данных. Кэширование берет на себя обработку этих запросов, освобождая базу данных для критически важных операций — например, обработки заказов. Это не только повышает скорость сайта, но и делает его более отказоустойчивым: даже если база "упадёт", данные всё ещё можно извлечь из кэша.

Итоги

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

1
Задача
Модуль 4: FastAPI, 9 уровень, 4 лекция
Недоступна
Кэширование REST-запросов
Кэширование REST-запросов
1
Задача
Модуль 4: FastAPI, 9 уровень, 4 лекция
Недоступна
Управление устаревшим кэшем
Управление устаревшим кэшем
3
Опрос
Кэширование с Redis, 9 уровень, 4 лекция
Недоступен
Кэширование с Redis
Кэширование с Redis
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ