每天40分玩转Django:Django缓存系统

Django缓存系统

一、今日学习内容概述

学习模块 重要程度 预计学时 主要内容
缓存基础概念 ⭐⭐⭐⭐⭐ 1小时 缓存原理、配置方式
Django内置缓存后端 ⭐⭐⭐⭐⭐ 2小时 内存、文件、数据库缓存
Redis缓存后端 ⭐⭐⭐⭐⭐ 2小时 Redis配置、使用方式
缓存最佳实践 ⭐⭐⭐⭐ 1小时 性能优化、策略设计

二、Django缓存配置

2.1 基本配置

python 复制代码
# settings.py

# Memcached配置
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

# Redis配置
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'PASSWORD': 'your-password',  # 如果有密码
        }
    }
}

# 文件系统缓存
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': '/var/tmp/django_cache',
        'TIMEOUT': 300,  # 5分钟
        'OPTIONS': {
            'MAX_ENTRIES': 1000,
            'CULL_FREQUENCY': 3,
        }
    }
}

# 本地内存缓存
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'unique-snowflake',
    }
}

三、缓存使用示例

3.1 视图级缓存

python 复制代码
# views.py
from django.views.decorators.cache import cache_page
from django.core.cache import cache
from django.shortcuts import render
from .models import Article

# 使用装饰器缓存整个视图
@cache_page(60 * 15)  # 缓存15分钟
def article_list(request):
    articles = Article.objects.all()
    return render(request, 'articles/list.html', {'articles': articles})

# 手动管理缓存
def article_detail(request, pk):
    cache_key = f'article_{pk}'
    article = cache.get(cache_key)
    
    if article is None:
        try:
            article = Article.objects.get(pk=pk)
            # 缓存文章,有效期1小时
            cache.set(cache_key, article, 60 * 60)
        except Article.DoesNotExist:
            return HttpResponse('文章不存在', status=404)
    
    return render(request, 'articles/detail.html', {'article': article})

3.2 模板片段缓存

html 复制代码
<!-- templates/articles/list.html -->
{% load cache %}

<div class="article-list">
    {% cache 300 'article_list' %}
    {% for article in articles %}
        <div class="article-item">
            <h2>{{ article.title }}</h2>
            <p>{{ article.summary }}</p>
        </div>
    {% endfor %}
    {% endcache %}
</div>

3.3 自定义缓存类

python 复制代码
# cache_utils.py
from django.core.cache import cache
from functools import wraps
import hashlib
import json

class CacheManager:
    def __init__(self, timeout=300):
        self.timeout = timeout
    
    def generate_key(self, *args, **kwargs):
        """生成缓存键"""
        key_dict = {
            'args': args,
            'kwargs': kwargs
        }
        key_str = json.dumps(key_dict, sort_keys=True)
        return hashlib.md5(key_str.encode()).hexdigest()
    
    def cache_decorator(self, prefix=''):
        """缓存装饰器"""
        def decorator(func):
            @wraps(func)
            def wrapper(*args, **kwargs):
                cache_key = f"{prefix}_{self.generate_key(*args, **kwargs)}"
                result = cache.get(cache_key)
                
                if result is None:
                    result = func(*args, **kwargs)
                    cache.set(cache_key, result, self.timeout)
                
                return result
            return wrapper
        return decorator
    
    def invalidate(self, prefix='', *args, **kwargs):
        """清除缓存"""
        cache_key = f"{prefix}_{self.generate_key(*args, **kwargs)}"
        cache.delete(cache_key)

# 使用示例
cache_manager = CacheManager(timeout=3600)

@cache_manager.cache_decorator(prefix='get_user_data')
def get_user_data(user_id):
    # 耗时的数据库查询
    return User.objects.get(id=user_id).get_full_data()

四、Redis缓存实现

4.1 Redis缓存管理器

python 复制代码
# redis_cache.py
import json
from django_redis import get_redis_connection
from datetime import datetime

class RedisCacheManager:
    def __init__(self, connection='default'):
        self.redis = get_redis_connection(connection)
    
    def set_json(self, key, data, timeout=None):
        """存储JSON数据"""
        json_data = json.dumps(data)
        if timeout:
            self.redis.setex(key, timeout, json_data)
        else:
            self.redis.set(key, json_data)
    
    def get_json(self, key):
        """获取JSON数据"""
        data = self.redis.get(key)
        if data:
            return json.loads(data)
        return None
    
    def increment(self, key, amount=1):
        """递增计数器"""
        return self.redis.incr(key, amount)
    
    def expire(self, key, timeout):
        """设置过期时间"""
        self.redis.expire(key, timeout)
    
    def delete(self, key):
        """删除键"""
        self.redis.delete(key)
    
    def clear_prefix(self, prefix):
        """清除指定前缀的所有键"""
        keys = self.redis.keys(f"{prefix}:*")
        if keys:
            self.redis.delete(*keys)

# 使用示例
class ArticleService:
    def __init__(self):
        self.cache = RedisCacheManager()
    
    def get_article_cache_key(self, article_id):
        return f"article:{article_id}"
    
    def get_article(self, article_id):
        cache_key = self.get_article_cache_key(article_id)
        article_data = self.cache.get_json(cache_key)
        
        if not article_data:
            article = Article.objects.get(id=article_id)
            article_data = {
                'id': article.id,
                'title': article.title,
                'content': article.content,
                'updated_at': article.updated_at.isoformat()
            }
            self.cache.set_json(cache_key, article_data, timeout=3600)
        
        return article_data

五、缓存流程图

六、高级缓存策略

6.1 分层缓存

python 复制代码
class LayeredCache:
    def __init__(self):
        self.local_cache = caches['local']
        self.redis_cache = caches['redis']
    
    def get(self, key):
        # 先查本地缓存
        value = self.local_cache.get(key)
        if value is not None:
            return value
            
        # 查Redis缓存
        value = self.redis_cache.get(key)
        if value is not None:
            # 写入本地缓存
            self.local_cache.set(key, value, timeout=60)
            return value
            
        return None
    
    def set(self, key, value, timeout=None):
        # 同时写入本地缓存和Redis
        self.local_cache.set(key, value, timeout=min(timeout, 60) if timeout else 60)
        self.redis_cache.set(key, value, timeout=timeout)

6.2 缓存预热

python 复制代码
# cache_warmer.py
from django.core.cache import cache
from django.db.models import Q
from datetime import datetime, timedelta

class CacheWarmer:
    def __init__(self):
        self.cache = cache
    
    def warm_article_cache(self):
        """预热热门文章缓存"""
        # 获取最近一周的热门文章
        recent_date = datetime.now() - timedelta(days=7)
        popular_articles = Article.objects.filter(
            Q(created_at__gte=recent_date) | 
            Q(view_count__gte=1000)
        ).select_related('author')
        
        for article in popular_articles:
            cache_key = f'article_{article.id}'
            self.cache.set(cache_key, article, timeout=3600)
            
        return len(popular_articles)

# 在Django管理命令中使用
from django.core.management.base import BaseCommand

class Command(BaseCommand):
    help = '预热缓存'
    
    def handle(self, *args, **kwargs):
        warmer = CacheWarmer()
        count = warmer.warm_article_cache()
        self.stdout.write(
            self.style.SUCCESS(f'Successfully warmed cache for {count} articles')
        )

七、缓存监控和管理

python 复制代码
# cache_monitor.py
from django.core.cache import cache
import time
import logging

logger = logging.getLogger(__name__)

class CacheMonitor:
    def __init__(self):
        self.cache = cache
    
    def monitor_operation(self, operation_name):
        """监控缓存操作的装饰器"""
        def decorator(func):
            def wrapper(*args, **kwargs):
                start_time = time.time()
                try:
                    result = func(*args, **kwargs)
                    elapsed_time = time.time() - start_time
                    self.log_operation(operation_name, True, elapsed_time)
                    return result
                except Exception as e:
                    elapsed_time = time.time() - start_time
                    self.log_operation(operation_name, False, elapsed_time, str(e))
                    raise
            return wrapper
        return decorator
    
    def log_operation(self, operation, success, elapsed_time, error=None):
        """记录缓存操作日志"""
        log_data = {
            'operation': operation,
            'success': success,
            'elapsed_time': elapsed_time,
            'error': error
        }
        
        if success:
            logger.info(f'Cache operation: {operation}', extra=log_data)
        else:
            logger.error(f'Cache operation failed: {operation}', extra=log_data)

八、性能优化建议

  1. 缓存键设计
  • 使用有意义的前缀
  • 避免过长的键名
  • 考虑版本号机制
  1. 缓存粒度
  • 合理划分缓存单位
  • 避免过大的缓存对象
  • 考虑部分字段缓存
  1. 缓存策略
  • 设置合适的过期时间
  • 实现缓存预热机制
  • 使用分层缓存提高命中率
  1. 缓存清理
  • 及时清理过期缓存
  • 实现缓存更新机制
  • 避免缓存穿透

九、总结

今天我们学习了:

  1. Django缓存系统的基本配置
  2. 多种缓存后端的使用方法
  3. 自定义缓存管理器的实现
  4. 缓存性能优化策略

怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

相关推荐
RemainderTime3 分钟前
(四)Spring Cloud Alibaba 2023.x:高效构建 Gateway 网关服务
后端·spring·spring cloud·微服务
拓端研究室10 分钟前
MATLAB图卷积神经网络GCN处理分子数据集节点分类研究
人工智能·分类·数据挖掘
Luzem031916 分钟前
OpenCV中的边缘检测和轮廓处理
人工智能·opencv·计算机视觉
野蛮的大西瓜22 分钟前
BigBlueButton目前支持哪些操作系统和浏览器
人工智能·机器人·自动化·音视频·信息与通信
serenity宁静22 分钟前
Focal Loss损失函数理解
人工智能·算法·机器学习
Adellle35 分钟前
判题机的开发(代码沙箱、三种模式、工厂模式、策略模式优化、代理模式)
java·后端·代理模式·策略模式
金金金__44 分钟前
探索:为什么数组数据后端确要求前端传递,拼接的字符呢
后端
Takoony1 小时前
理解 Python ProcessPoolExecutor 的序列化问题:为什么线程锁(threading.Lock)会导致异常?
linux·开发语言·python
只恨天高1 小时前
SpringBoot整合JDBC
java·spring boot·后端
道友老李1 小时前
【Python基础】入门(运算、输出、数据类型)
开发语言·python