Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Кеширование запросов в Django
Кеширование запросов — это техника оптимизации производительности, при которой результаты SQL-запросов сохраняются в памяти (кэше) для быстрого доступа в будущем. Это позволяет избежать повторных обращений к базе данных для одних и тех же данных, значительно снижая нагрузку на БД и время отклика приложения.
Уровни кеширования в Django
Django предоставляет несколько уровней кеширования:
- Кеширование на уровне БД — кэш результатов ORM запросов
- Кеширование представлений (View caching) — сохранение полного вывода представления
- Кеширование шаблонов — кэш отдельных блоков шаблонов
- Низкоуровневое кеширование — прямая работа с кэшем через
cacheAPI
Встроенные бэкенды кэша
Django поддерживает разные бэкенды кеширования:
# settings.py
CACHES = {
"default": {
"BACKEND": "django.core.cache.backends.redis.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
}
}
Доступные бэкенды: Redis, Memcached, файловая система, локальная память (разработка).
Кеширование представлений
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # Кэш на 15 минут
def my_view(request):
data = ExpensiveModel.objects.all()
return render(request, 'template.html', {'data': data})
Низкоуровневое кеширование
from django.core.cache import cache
# Сохранение в кэш
cache.set('user_profile_123', user_data, timeout=300) # 5 минут
# Получение из кэша
user_data = cache.get('user_profile_123')
# Получение или вычисление
data = cache.get_or_set('expensive_data', expensive_function, 600)
# Удаление из кэша
cache.delete('user_profile_123')
# Очистка всего кэша
cache.clear()
Кеширование запросов ORM
# Ручное кеширование результатов запроса
def get_user_posts(user_id):
cache_key = f'user_posts_{user_id}'
posts = cache.get(cache_key)
if posts is None:
posts = Post.objects.filter(user_id=user_id)
cache.set(cache_key, list(posts), 3600) # Кэш на час
return posts
Кеширование шаблонов
{% load cache %}
{% cache 500 sidebar user.id %}
<div class="sidebar">
<!-- дорогостоящий контент -->
</div>
{% endcache %}
Инвалидация кэша
Критически важно корректно инвалидировать (очищать) кэш при обновлении данных:
def update_user_profile(user_id, data):
user = User.objects.get(id=user_id)
for key, value in data.items():
setattr(user, key, value)
user.save()
# Инвалидируем кэш
cache.delete(f'user_profile_{user_id}')
cache.delete(f'user_posts_{user_id}')
Паттерны кеширования
Cache-Aside (Lazy Loading) — самый распространённый паттерн:
- Проверь кэш
- Если есть — верни
- Если нет — загрузи из БД, сохрани в кэш
Write-Through — при записи обновляй кэш одновременно:
def save_user(user):
user.save()
cache.set(f'user_{user.id}', user, 3600)
Практические советы
- Используй Redis или Memcached для production, не файловую систему
- Выбирай разумные timeout'ы (не слишком короткие, не слишком длинные)
- Инвалидируй кэш при каждом обновлении данных
- Используй версионирование ключей для безболезненного обновления формата
- Мониторь hit rate кэша (какой процент запросов из кэша)
- Избегай cache stampede — когда многие запросы одновременно заново вычисляют значение после истечения TTL
Кеширование — мощный инструмент для масштабирования, но требует тщательного проектирования инвалидации данных.