Django-redis设置timeout=None缓存JSON数分钟后自动清除如何解决
问题场景
- 基于Django搭建了控制天文圆顶+家庭自动化的小型站点,项目启动阶段需要加载
relays、conditions、homeautomation三个JSON配置文件 - 为降低树莓派4B挂载SSD的频繁读写损耗,在apps模块启动时将解析后的JSON数据存入Redis;该Redis通过Docker部署,原本为项目Celery组件提供服务
- 故障现象:写入Redis的JSON缓存仅能保留数分钟就会被自动清除
- 预期需求:不需要Redis宕机数据持久化,不需要对接数据库能力,仅要求缓存数据在服务运行全周期常驻,不被自动清理
现有实现
缓存写入代码
cache.set("REDIS_ashtreeautomation_dict", dict, timeout=None)
Django缓存配置
CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://redis:6379", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "SERIALIZER": "django_redis.serializers.json.JSONSerializer", "TIMEOUT": None } } }
排查与解决方案
你当前写的timeout=None配置在django-redis中本身就是代表永久不过期,语法和配置写法没有问题,缓存被自动清除基本都是以下几个原因导致,按优先级排查即可:
优先检查Redis内存淘汰策略(最高概率原因)
多数默认拉取的Redis Docker镜像没有自定义配置时,内存达到maxmemory阈值后会触发默认淘汰规则,常见的allkeys-lru、volatile-lru策略会自动删除旧键腾空间,哪怕键被设置为永久有效期也会被清理。- 排查方式:进入Redis容器执行
redis-cli CONFIG GET maxmemory-policy查看当前策略 - 修复方式:将淘汰策略改为
noeviction,该模式下Redis达到内存上限只会返回写入错误,不会删除任何已有键,完全匹配你的需求。临时生效可直接执行redis-cli CONFIG SET maxmemory-policy noeviction;要永久固定配置,在Docker启动Redis的命令/compose配置中追加启动参数--maxmemory-policy noeviction即可,同时可根据树莓派内存情况给Redis设置合理的maxmemory值(比如分配128-256M足够存储这类JSON配置),避免Redis吃光整机内存。
- 排查方式:进入Redis容器执行
排查Redis库键冲突问题
你的Redis同时承载Celery服务,默认Celery会使用Redis的db0库,如果Django缓存也用同一个db0,可能存在Celery过期清理逻辑误删、键名重复覆盖的问题。- 修复方式:给Django缓存单独分配独立的Redis逻辑库,将配置中
LOCATION字段改为redis://redis:6379/1,使用db1和Celery默认的db0做逻辑隔离,避免服务间互相干扰。另外不要用Python内置类型名dict作为存储数据的变量名,容易触发序列化时的不可预期问题,将待存储的配置字典改为有实际语义的变量名(比如domotic_config)再传入cache.set即可。
- 修复方式:给Django缓存单独分配独立的Redis逻辑库,将配置中
验证永久有效期是否实际生效
写入缓存后进入Redis执行redis-cli TTL REDIS_ashtreeautomation_dict,如果返回值为-1说明键确实被设置为永久有效期;如果返回其他正整数,说明存在全局中间件、其他启动逻辑覆写了缓存超时配置,全局搜索cache.set、缓存相关装饰器逻辑排查即可。
内容的提问来源于stack exchange,提问作者SgtBilko
相关产品推荐
相关产品推荐

