Django缓存功能如何配置?

访客 全栈框架 2

本文目录导读:

  1. 核心配置(settings.py
  2. 常用缓存后端配置
  3. 多缓存配置
  4. 缓存的时间
  5. 缓存键前缀设置
  6. 版本控制
  7. 实际使用示例
  8. 数据库查询缓存示例
  9. 信号驱动缓存失效
  10. 缓存中间件配置
  11. 缓存键的构造
  12. 性能与监控
  13. 常见问题与最佳实践

Django 的缓存系统非常灵活,支持多种后端(内存、数据库、文件系统、Redis/Memcached 等),以下是详细的配置和使用指南。

核心配置(settings.py

首先在 settings.py 中设置 CACHES 字典:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',  # 本地内存缓存(默认)
        'LOCATION': 'unique-snowflake',  # 用于区分多个内存缓存的名称
        'TIMEOUT': 300,  # 默认超时时间:300秒(5分钟)
        'OPTIONS': {
            'MAX_ENTRIES': 300,  # 最大缓存条目数
            'CULL_FREQUENCY': 3,  # 达到 MAX_ENTRIES 时,删除三分之一条目
        }
    }
}

常用缓存后端配置

1 文件系统缓存

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': '/var/tmp/django_cache',  # 必须是绝对路径
    }
}

2 数据库缓存

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'my_cache_table',  # 数据库表名
    }
}
# 需要创建缓存表:python manage.py createcachetable

3 Memcached 缓存

# 方式1:使用 python-memcached 库
CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',
        'LOCATION': [
            '127.0.0.1:11211',  # 单实例
            # 也可以配置多台服务器
            # '10.0.1.10:11211',
            # '10.0.1.11:11211',
        ],
        'TIMEOUT': 300,
    }
}
# 方式2:使用 pylibmc 库(性能更好)
# CACHES = {
#     'default': {
#         'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
#         'LOCATION': '127.0.0.1:11211',
#     }
# }

4 Redis 缓存(最推荐)

# 需要安装:pip install django-redis
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',  # Redis URL
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'SOCKET_CONNECT_TIMEOUT': 5,  # 连接超时
            'SOCKET_TIMEOUT': 5,          # 读写超时
            'PASSWORD': 'yourpassword',   # 如果有密码
            'PARSER_CLASS': 'redis.connection.HiredisParser',  # 提高性能
            'CONNECTION_POOL_CLASS': 'redis.BlockingConnectionPool',
            'CONNECTION_POOL_CLASS_KWARGS': {
                'max_connections': 100,
                'timeout': 20,
            },
        }
    }
}
# 也可以配置多个 Redis 实例(主从、哨兵等)
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': [
            'redis://127.0.0.1:6379/1',
            'redis://127.0.0.1:6378/1',  # 备用
        ],
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.SentinelClient',  # 哨兵模式
            'SENTINEL_KWARGS': {'master_name': 'mymaster'},
        }
    }
}

多缓存配置

可以同时配置多个缓存后端,用于不同场景:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379',
        'TIMEOUT': 300,
    },
    'session': {
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'session_cache_table',
        'TIMEOUT': 86400,  # 24小时
    },
    'staticfiles': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': '/var/tmp/django_static_cache',
        'TIMEOUT': 86400 * 30,  # 30天
    }
}

缓存的时间

全局设置与局部设置:

# settings.py 中全局设置
CACHE_MIDDLEWARE_ALIAS = 'default'        # 中间件使用的缓存别名
CACHE_MIDDLEWARE_SECONDS = 600            # 缓存时间(秒)
CACHE_MIDDLEWARE_KEY_PREFIX = 'myapp'     # 缓存键前缀
# 使用 site 框架时自动设置
CACHE_MIDDLEWARE_ANONYMOUS_ONLY = True    # 仅缓存匿名用户

缓存键前缀设置

# 方案1:在配置中设置 KEY_PREFIX
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379',
        'KEY_PREFIX': 'mysite_'  # 所有缓存键都会带此前缀
    }
}
# 方案2:使用 site 框架自动添加站点前缀
INSTALLED_APPS = [
    'django.contrib.sites',
]
# 设置 SITE_ID 后,缓存键会自动包含站点标识

版本控制

CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379',
        'VERSION': 1,  # 整数版本号
        'KEY_FUNCTION': 'django.core.cache.utils.make_key',
        'VERSION_BASED_KEY_FUNCTION': 'django.core.cache.utils.default_key_func',
    }
}
# 运行时改变版本号(会清空之前版本的缓存)
from django.core.cache import cache
cache.version = 2  # 当前版本

实际使用示例

1 视图缓存(装饰器)

from django.views.decorators.cache import cache_page
@cache_page(60 * 15)  # 缓存15分钟
def my_view(request):
    # 耗时操作
    return render(request, 'template.html')
# 也可以用在 URLconf 中
from django.views.decorators.cache import cache_page
urlpatterns = [
    path('my_view/', cache_page(60 * 15)(my_view)),
]

2 片段缓存(模板中使用)

{% load cache %}
{% cache 500 "sidebar" %}
    {# 这里的内容会被缓存500秒 #}
    {% for item in items %}
        <li>{{ item.name }}</li>
    {% endfor %}
{% endcache %}
{% cache 3600 "sidebar" request.user.username %}
    {# 基于用户的缓存 #}
    <div>欢迎 {{ request.user.username }}</div>
{% endcache %}

3 低级别缓存 API

from django.core.cache import cache
# 设置缓存
cache.set('my_key', 'my_value', timeout=300)  # 5分钟
cache.set_many({'key1': 'val1', 'key2': 'val2'}, timeout=60)
# 获取缓存
value = cache.get('my_key')
values = cache.get_many(['key1', 'key2'])
# 使用 get_or_set
value = cache.get_or_set('expensive_key', 'default_value', 300)
# 原子操作(增加/减少)
cache.incr('counter', delta=1)
cache.decr('counter', delta=1)
# 获取后删除(原子操作)
value = cache.get_and_delete('my_key')
# 删除缓存
cache.delete('my_key')
cache.delete_many(['key1', 'key2'])
# 清空整个缓存(谨慎使用)
cache.clear()
# 检查键是否存在
has_key = cache.has_key('my_key')
# 手动设置超时时间
cache.touch('my_key', timeout=600)  # 重置为10分钟
# 设置默认超时(使用配置中的默认值)
cache.set('key', 'value')  # 使用全局TIMEOUT
# 批量操作
cache.set('key1', 'val1', 60)
cache.set('key2', 'val2', 120)
# cache.set_many({'key1': 'val1', 'key2': 'val2'}, timeout=300)  # 统一超时
# 使用键前缀
from django.core.cache import cache
cache.set('raw_key', 'value')
# 实际存储时为 'mysite_:1:raw_key'(假设前缀为 mysite_,版本为1)
# 设置过期时间的 Unix 时间戳
import time
cache.set('key', 'value', timeout=int(time.time()) + 3600)  # 1小时后过期
# 检查缓存是否可用
cache.ping()  # 如果可用返回 True,否则抛出异常

数据库查询缓存示例

from django.core.cache import cache
from .models import Article
def get_article_list():
    # 尝试从缓存获取
    articles = cache.get('article_list')
    if articles is None:
        # 缓存未命中,从数据库查询
        articles = list(Article.objects.all().select_related('author'))
        # 存入缓存,设置超时时间
        cache.set('article_list', articles, 300)
    return articles
# 更简洁的方式
def get_article_list_v2():
    articles = cache.get_or_set(
        'article_list',
        lambda: list(Article.objects.all().select_related('author')),
        300  # 缓存5分钟
    )
    return articles

信号驱动缓存失效

from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django.core.cache import cache
from .models import Article
@receiver(post_save, sender=Article)
@receiver(post_delete, sender=Article)
def clear_article_cache(sender, **kwargs):
    # 文章保存或删除时清除相关缓存
    cache.delete('article_list')
    cache.delete(f'article_detail_{kwargs["instance"].id}')
# 也可以在 post_save 信号中更新缓存
@receiver(post_save, sender=Article)
def update_article_cache(sender, instance, created, **kwargs):
    if created:
        # 添加到缓存
        article_list = cache.get('article_list') or []
        article_list.append(instance)
        cache.set('article_list', article_list, 300)
    else:
        # 更新缓存
        cache.delete('article_list')

缓存中间件配置

# settings.py 添加中间件
MIDDLEWARE = [
    'django.middleware.cache.UpdateCacheMiddleware',  # 放在最前面
    # ... 其他中间件 ...
    'django.middleware.common.CommonMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',  # 放在最后
]
CACHE_MIDDLEWARE_ALIAS = 'default'
CACHE_MIDDLEWARE_SECONDS = 600
CACHE_MIDDLEWARE_KEY_PREFIX = ''  # 可选前缀

缓存键的构造

# 默认键函数生成:key_prefix:version:key
# mysite_:1:article_list
# 自定义键函数
def my_key_func(key, key_prefix, version):
    return f'{key_prefix}:{version}:{key}'
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379',
        'KEY_FUNCTION': 'my_app.cache.my_key_func',  # 自定义键函数
    }
}

性能与监控

# 启用缓存统计
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'SETTINGS': {
                'CACHE_HIT_RATIO': True,  # 启用命中率统计
            }
        }
    }
}
# 获取缓存统计信息
from django_redis import get_redis_connection
connection = get_redis_connection('default')
info = connection.info()
print(info['keyspace_hits'], info['keyspace_misses'])  # 命中/未命中

常见问题与最佳实践

  1. 缓存失效策略:对于频繁更新的数据,使用较短的超时时间;对于不常变化的数据,使用较长的超时时间
  2. 键命名规范:使用有意义的、唯一的键名,避免冲突
  3. 版本管理:代码更新后,考虑增加缓存版本号以强制刷新
  4. 异常处理:缓存后端不可用时,应有降级策略(如直接查询数据库)
  5. 监控:监控缓存命中率,及时调整策略
  6. 安全性:不要缓存敏感信息(密码、个人隐私等)

选择合适的缓存后端取决于你的项目规模、性能需求和可用的基础设施,对于大多数中小型项目,Redis 是最推荐的选项,它提供了高性能、持久化选项和丰富的数据结构支持。

标签: Redis

抱歉,评论功能暂时关闭!