Ответ
Существует два фундаментальных подхода к реализации кэширования, различающихся местом хранения данных:
1. Кэширование в памяти (In-Memory Caching)
Данные хранятся непосредственно в оперативной памяти (RAM) приложения. Этот подход обеспечивает максимальную скорость доступа.
- Преимущества:
- Очень низкая задержка (latency), так как нет сетевых запросов.
- Простота реализации для кэширования внутри одного процесса.
- Недостатки:
- Энергозависимость: кэш очищается при перезапуске или сбое приложения.
- Масштабируемость: кэш ограничен объемом RAM одного сервера и недоступен для других экземпляров приложения.
Пример в Python (мемоизация):
Декоратор functools.lru_cache кэширует результаты вызовов функции.
from functools import lru_cache
import time
@lru_cache(maxsize=128)
def expensive_calculation(n):
"""Имитация долгой операции"""
time.sleep(1)
return n * n
# Первый вызов займет 1 секунду
print(expensive_calculation(10))
# Второй вызов вернет результат из кэша мгновенно
print(expensive_calculation(10))
2. Внешнее кэширование (External/Distributed Caching)
Данные хранятся в отдельном, независимом сервисе (например, Redis, Memcached), к которому приложение обращается по сети.
- Преимущества:
- Персистентность: данные сохраняются между перезапусками приложения.
- Масштабируемость: кэш может быть общим для множества экземпляров приложения или микросервисов.
- Больший объем хранения, ограниченный только ресурсами кэш-сервера.
- Недостатки:
- Более высокая задержка из-за сетевых вызовов.
- Требует развертывания и поддержки дополнительной инфраструктуры.
Пример в Python с Redis:
import redis
# Подключение к серверу Redis
r = redis.Redis(host='localhost', port=6379, db=0)
# Сохранение значения в кэш с временем жизни 60 секунд
r.set('user:1:profile', '{"name": "Alice"}', ex=60)
# Получение значения из кэша
cached_profile = r.get('user:1:profile')
if cached_profile:
print(cached_profile.decode('utf-8'))