Django 4 默认不支持 Redis 原生 Session 后端,必须用 django-redis:SESSION_ENGINE 必须设为 django.contrib.sessions.backends.cache,CACHES"default" 必须为 django_redis.cache.RedisCache,二者缺一不可。

直接上结论:Django 4 默认不支持 Redis 原生 Session 后端,必须用第三方库(如 django-redis 或 django-redis-sessions),且关键配置项不能写错——SESSION_ENGINE 必须设为 django.contrib.sessions.backends.cache,同时 CACHES["default"]["BACKEND"] 必须指向 django_redis.cache.RedisCache,二者缺一不可。
为什么 django-redis 是当前最稳的选择
Django 4 移除了对 redis_sessions 这类老库的兼容支持,而 django-redis 已成为事实标准:它提供完整的连接池、序列化控制、自动重连和 TTL 管理。更重要的是,它让 Session 的过期逻辑真正落地——不是靠 Python 层定时清理,而是靠 Redis 自带的 EXPIRE 指令。
常见错误现象:redis-cli keys "session:*" 能查到 key,但 ttl "session:abc123" 返回 -1(永不过期);或内存持续上涨,INFO memory 显示 used_memory 不降。
- 根本原因:没配
CACHES["default"]["BACKEND"],或误配成django.core.cache.backends.redis.RedisCache(Django 4.2+ 已弃用) - 正确值必须是
django_redis.cache.RedisCache - 必须确保
SESSION_CACHE_ALIAS = "default",否则 Django 会 fallback 到数据库后端 - 若用 Unix socket 连接 Redis,
LOCATION要写成unix:///var/run/redis/redis-server.sock?db=1,不能漏掉?db=1
SESSION_COOKIE_DOMAIN 和 secure 配置必须匹配部署拓扑
多实例 + Nginx 反向代理下,Session 丢失往往不是 Redis 写失败,而是浏览器压根没把 sessionid Cookie 发回来——因为 domain 或 secure 标志不匹配。
立即学习“Python免费学习笔记(深入)”;
使用场景:Nginx 终止 HTTPS,后端 Django 走 HTTP;域名含 www.example.com 和 api.example.com 两个子域。
-
SESSION_COOKIE_DOMAIN = ".example.com"(开头必须带点),否则子域间无法共享 -
SESSION_COOKIE_SECURE = True仅在 HTTPS 请求中生效;Nginx 终止 SSL 时,需加SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") -
SESSION_COOKIE_HTTPONLY = True和SESSION_COOKIE_SAMESITE = "Lax"必须显式设置,避免被 JS 窃取或跨站表单丢 session - Nginx 配置里要透传
X-Forwarded-Proto和Host头,否则 Django 无法判断真实协议
如何验证 Session 真正写进了 Redis 并带 TTL
别只看浏览器 Cookie 里有没有 sessionid,那只是“发出去了”;要确认“Redis 收到了,且设了过期时间”。
操作步骤:
- 登录后,在 Django shell 中执行:
from django.contrib.sessions.models import Session; Session.objects.get(pk=request.session.session_key)—— 若报Session.DoesNotExist,说明没进 DB,但可能进了 cache;此时检查CACHES配置 - 用
redis-cli -n 1 keys "session:*"(注意 db 编号)确认 key 存在 - 执行
redis-cli -n 1 ttl "session:xxx",返回值应为正整数(如 1209600),不是-1(永不过期)或-2(key 不存在) - 手动触发过期:执行
redis-cli -n 1 expire "session:xxx" 2,2 秒后刷新页面,应跳转登录页
容易被忽略的一点:Django 的 SESSION_COOKIE_AGE 控制的是 Cookie 过期时间,而 Redis key 的 TTL 由 get_expiry_age() 决定,默认等于 SESSION_COOKIE_AGE,但若视图中调用了 request.session.set_expiry(3600),则以该值为准——这个细节在调试超时行为时经常翻车。


















