讲师中心 微信公众号

工具推荐

视频效率加速
AniShort
AniShort

AI短剧协同制作平台

立刻MV
立刻MV

低成本歌曲 MV、视频生成

Laper
Laper

剧本策划到成片协作

剧云
剧云

中文短剧剧本制作平台

如何在Django中通过Redis Cache安全处理不存在的查询对象?

梦涛同学_4974

梦涛同学_4974

发布时间:2026-11-15 05:08:03

|

656人浏览过

|

来源于php中文网

原创

Django的cache.get()返回None无法区分缓存未命中与数据库查无结果,应使用哨兵值(如_MISSING=object())显式标记“不存在”,并分设合理超时以防止缓存穿透。

如何在django中通过redis cache安全处理不存在的查询对象?

直接说结论:Django 的 cache.get() 返回 None 是正常行为,但“安全处理不存在的查询对象”关键不在缓存层,而在如何区分「缓存未命中」和「数据库查无此对象」——否则会缓存空结果或引发 N+1 查询。

为什么 cache.get() 无法区分「没缓存」和「缓存了 None」?

Django 默认的 cache.get(key) 在 key 不存在或显式存入 None 时都返回 None。如果你在数据库查不到对象后写入 cache.set(key, None),后续就无法判断这次 None 是缓存穿透防护(故意存的),还是单纯还没缓存过。

  • 典型错误模式:obj = cache.get(key); if obj is None: obj = MyModel.objects.get(id=123); cache.set(key, obj) —— 一旦 MyModel.objects.get() 抛 MyModel.DoesNotExist,obj 仍为 None,被误存进缓存,导致永久性缓存穿透
  • 正确做法是捕获异常,并用特殊标记(如 cache.set(key, _MISSING, timeout=...))显式表示「查无此数据」
  • 推荐用哨兵值(例如 _MISSING = object()),避免和业务中可能合法的 None 冲突

用 cache.get_or_set() 要小心它的「原子性假象」

cache.get_or_set(key, default_func, timeout) 看似能省掉条件判断,但它只保证「获取 + 设置」的原子性,不保证 default_func 执行本身是幂等的——尤其当 default_func 是数据库查询时,多个并发请求仍可能同时触发多次 DB 查询。

Sentinal Redis
Sentinal Redis

监控Redis服务器健康状况、内存、性能及BullMQ队列。检查队列深度、失败任务,分析慢查询并诊断问题。

下载
  • 问题场景:高并发下,key 第一次失效,10 个请求同时调用 cache.get_or_set(..., lambda: MyModel.objects.get(id=123)),全部执行 .get(),造成 DB 压力
  • 缓解方案:对热点 key 加一层本地锁(如 threading.Lock 或 redis.lock),或改用 cache.add() 配合后台异步加载
  • 更稳妥的写法是手动实现「先 get → 检查是否 _MISSING → 否则查 DB → 成功则 set,失败则 set _MISSING」

推荐的健壮缓存读取模式(含 Redis 特性利用)

利用 Redis 的 GET 原语天然返回 nil(对应 Python None),再配合 Django cache backend 的 get_many() 批量探查能力,可减少网络往返。但核心仍是逻辑分层清晰:

from django.core.cache import cache
<p>_MISSING = object()  # 全局唯一哨兵</p><p>def get_cached_model_instance(model_class, pk):
cache_key = f"{model_class._meta.db_table}:pk:{pk}"
cached = cache.get(cache_key)
if cached is _MISSING:
return None  # 明确知道 DB 里没有
if cached is not None:
return cached  # 缓存命中</p><h1>缓存未命中:查 DB</h1><pre class='brush:php;toolbar:false;'>try:
    obj = model_class.objects.get(pk=pk)
    cache.set(cache_key, obj, timeout=300)
    return obj
except model_class.DoesNotExist:
    cache.set(cache_key, _MISSING, timeout=60)  # 短期缓存「不存在」,防穿透
    return None
  • 注意 _MISSING 的 timeout 应显著短于有效对象的 timeout(比如 60s vs 300s),避免长期阻塞重试
  • 如果用的是 django-redis,可进一步用 cache.client.get_client().exists(cache_key) 判断 key 是否真实存在于 Redis 中(绕过 Django cache 的抽象层),用于调试或监控缓存穿透率
  • 不要把模型实例直接塞进 cache——序列化/反序列化开销大,且可能带循环引用;建议只缓存必要字段字典或使用 model_to_dict()

最易被忽略的一点:缓存「不存在」状态时,timeout 时间必须可控。设太长会导致数据实际已写入 DB 后,缓存还在拒绝响应,形成短暂但可感知的数据不一致;设太短又起不到防穿透作用。这个平衡点得结合你的更新频率和业务容忍度手工调优,没有通用值。

热门AI工具

更多
豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

SoundView
SoundView Hot

SoundView是一款面向跨境电商的视频翻译、配音和本地化 AI 创作平台。

花生AI
花生AI Hot

一款AI视频创作工具,主要用于B站推出的AI视频创作工具,适合需要提升相关任务效率的用户。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

相关专题

更多
Python Web 框架 Django 深度开发
Python Web 框架 Django 深度开发

本专题系统讲解 Python Django 框架的核心功能与进阶开发技巧,包括 Django 项目结构、数据库模型与迁移、视图与模板渲染、表单与认证管理、RESTful API 开发、Django 中间件与缓存优化、部署与性能调优。通过实战案例,帮助学习者掌握 使用 Django 快速构建功能全面的 Web 应用与全栈开发能力。

613

2026.02.04

Python Django REST Framework接口安全与认证体系实践
Python Django REST Framework接口安全与认证体系实践

本专题围绕 Django REST Framework 展开,深入讲解 API 认证、JWT 鉴权、权限控制、接口安全防护以及防攻击策略设计。通过完整后端案例,帮助开发者构建安全可靠的 Web API 服务体系。

280

2026.06.29

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

4969

2023.11.02

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

4555

2023.11.14

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

8852

2024.04.02

redis怎么做缓存服务器
redis怎么做缓存服务器

redis 作为缓存服务器的答案:redis 是一款开源、高性能、分布式的键值存储,可作为缓存服务器使用。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

683

2024.04.07

redis怎么解决数据一致性
redis怎么解决数据一致性

redis 提供了两种一致性模型,以维护副本数据一致性:强一致性 (sync) 确保写操作仅在复制到所有从节点后才完成;最终一致性 (async) 则在主节点上写操作后认为已完成,牺牲一致性换取性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

776

2024.04.07

mysql和redis怎么保证双写一致性
mysql和redis怎么保证双写一致性

确保 mysql 和 redis 双写一致性的技术包括:1、事务性更新:同时更新 mysql 和 redis,保证一致性;2、主从复制:mysql 主服务器更改同步到 redis 从服务器;3、基于事件的更新:mysql 记录更改并发送到 redis等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

9262

2024.04.07

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

40

2026.11.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go-Zero官方文档
Go-Zero官方文档

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn