如何在Django请求间高效共享大型不可变Python对象?
Django中共享大型不可变内存对象的最优方案
针对你需要在Django里共享35M左右的只读字典、不想用pickle和Redis、只靠重启更新的需求,最贴合Django风格且性能最优的方式是把对象加载到模块级全局变量中,具体实现和注意事项如下:
核心思路
模块级变量会在Django进程启动时加载一次,之后所有请求的线程都能直接读取,完全绕开序列化/反序列化的开销,也不需要额外依赖组件,完全符合你的需求。而且因为对象是不可变的,天然线程安全,不用担心并发问题。
具体实现步骤
- 在你的Django应用下新建一个专门的模块,比如
data_store.py,用来存放加载逻辑:
# myapp/data_store.py import json from django.conf import settings # 全局变量,仅在模块加载时初始化一次 LARGE_DATA = None def load_large_data(): global LARGE_DATA if LARGE_DATA is None: # 用Django配置的路径定位数据文件,避免硬编码 data_path = settings.BASE_DIR / "data" / "large_dictionary.json" with open(data_path, 'r', encoding='utf-8') as f: LARGE_DATA = json.load(f) # 模块加载时自动执行数据加载 load_large_data()
- 在视图、表单或其他需要用数据的地方直接导入使用:
# myapp/views.py from django.http import JsonResponse from .data_store import LARGE_DATA def query_data(request): key = request.GET.get('key') value = LARGE_DATA.get(key, '不存在该键') return JsonResponse({'key': key, 'value': value})
关键注意事项
- 多进程部署的内存占用:如果用Gunicorn这类多进程服务器,每个worker进程都会单独加载一份35M的数据到内存,所以要根据服务器内存情况调整worker数量,避免内存溢出。
- 更新数据流程:直接替换磁盘上的数据文件,然后重启所有Django worker进程即可完成更新,完全符合你“愿意重启更新”的前提。
- 数据加载时机:模块级代码会在Django启动时执行,确保请求到来前数据已经加载完成,不会出现请求时才加载导致的延迟。
对比其他方案的优势
- 比Django内存缓存更高效:不需要把对象pickle序列化,也不存在每次请求反序列化的性能损耗,直接内存读写速度最快。
- 比第三方缓存后端更可靠:不用依赖像django-lrucache-backend这类久未维护的库,减少潜在的兼容性问题。
- 比Redis更省心:不需要额外部署和维护Redis服务,减少运维复杂度,也避免了网络IO的开销。
内容的提问来源于stack exchange,提问作者dfrankow
相关产品推荐
相关产品推荐

