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)  # Виконання eval рядка в 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": "Користувача успішно оновлено"}
    return {"msg": "Користувача не знайдено"}

Навіщо це потрібно в реальному житті?

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

Підсумки

Ми реалізували кешування частих запитів, пропрацювали сценарії інвалідизації даних і перевірили їх інтеграцію в FastAPI. Redis — це потужний інструмент, який, як чарівний носок з подарунками, зберігає дані для швидкого використання. Практикуйтесь, експериментуйте і пам'ятайте: кешування — це не костиль, а стратегічна частина будь-якої архітектури.

3
Опитування
Кешування з Redis, рівень 9, лекція 4
Недоступний
Кешування з Redis
Кешування з Redis
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ