Django项目Redis缓存性能异常:带缓存接口为何更慢?
Django中Redis缓存接口性能异常降低的问题排查
测试数据对比
无缓存接口(person)测试结果
[Thu Mar 23 2023 17:48:01 GMT+0530 (India Standard Time)] INFO Max requests: 50 [Thu Mar 23 2023 17:48:01 GMT+0530 (India Standard Time)] INFO Concurrency level: 1 [Thu Mar 23 2023 17:48:01 GMT+0530 (India Standard Time)] INFO Agent: none [Thu Mar 23 2023 17:48:01 GMT+0530 (India Standard Time)] INFO [Thu Mar 23 2023 17:48:01 GMT+0530 (India Standard Time)] INFO Completed requests: 50 [Thu Mar 23 2023 17:48:01 GMT+0530 (India Standard Time)] INFO Total errors: 0 [Thu Mar 23 2023 17:48:01 GMT+0530 (India Standard Time)] INFO Total time: 0.40408834 s [Thu Mar 23 2023 17:48:01 GMT+0530 (India Standard Time)] INFO Requests per second: 124 [Thu Mar 23 2023 17:48:01 GMT+0530 (India Standard Time)] INFO Mean latency: 8 ms
带缓存接口(person1)测试结果
[Thu Mar 23 2023 17:47:56 GMT+0530 (India Standard Time)] INFO Max requests: 50 [Thu Mar 23 2023 17:47:56 GMT+0530 (India Standard Time)] INFO Concurrency level: 1 [Thu Mar 23 2023 17:47:56 GMT+0530 (India Standard Time)] INFO Agent: none [Thu Mar 23 2023 17:47:56 GMT+0530 (India Standard Time)] INFO [Thu Mar 23 2023 17:47:56 GMT+0530 (India Standard Time)] INFO Completed requests: 50 [Thu Mar 23 2023 17:47:56 GMT+0530 (India Standard Time)] INFO Total errors: 0 [Thu Mar 23 2023 17:47:56 GMT+0530 (India Standard Time)] INFO Total time: 18.811554342 s [Thu Mar 23 2023 17:47:56 GMT+0530 (India Standard Time)] INFO Requests per second: 3 [Thu Mar 23 2023 17:47:56 GMT+0530 (India Standard Time)] INFO Mean latency: 376.1 ms
接口实现代码
def person(request): if 'auth' in request.session and request.session['auth']: res_all = Person.objects.values().all() return render(request,'blog.html',context={"all_data":res_all}) else: return render(request,'blog.html',context={}) def person1(request): cache_data=cache.get('cache_key_person') if cache_data: return render(request,'blog.html',context={"all_data":cache_data}) else: res_all = Person.objects.values().all() cache.set('cache_key_person', res_all, CACHE_TTL) return render(request,'blog.html',context={"all_data":res_all})
问题根因分析
带缓存接口性能暴跌的核心原因是缓存了未执行的QuerySet对象:
- Django的
Person.objects.values().all()返回的是惰性求值的QuerySet,它不是实际查询结果,而是包含数据库连接、查询参数等大量冗余信息的查询构造器。 - 调用
cache.set存储该QuerySet时,Django会通过pickle对其序列化,这个过程耗时极长,且生成的序列化数据体积远大于实际查询结果。 - 后续从缓存获取数据时,还要对庞大的序列化对象反序列化,进一步拉长请求响应时间。
- 无缓存接口中,
Person.objects.values().all()在传递给模板时才执行查询,直接返回字典列表,无额外序列化/反序列化开销,若数据库本身查询速度快,整体性能自然远超带缓存接口。
修复方案
修改带缓存接口,将QuerySet执行后的实际结果存入缓存:
def person1(request): cache_data=cache.get('cache_key_person') if cache_data: return render(request,'blog.html',context={"all_data":cache_data}) else: # 将QuerySet转为列表,执行查询并获取实际结果 res_all = list(Person.objects.values().all()) cache.set('cache_key_person', res_all, CACHE_TTL) return render(request,'blog.html',context={"all_data":res_all})
额外优化检查点:
- 确认Redis连接配置合理性,避免每次请求新建连接(Django默认Redis缓存后端维护连接池,配置错误会导致连接开销过大)。
- 若
Person表数据量较大,可考虑对缓存结果分页,避免一次性缓存过多数据。
内容的提问来源于stack exchange,提问作者Amit
相关产品推荐
相关产品推荐

