一、为什么要使用缓存

大家可以想一下Django的请求响应流程:

→ 用户浏览器输入URL地址

→ Web服务器将HTTP请求转发给uWSGI服务器

→ uWSGI服务器将Request请求转发给Django应用

→ Django中间件处理Request请求

→ 视图View处理

→ 模型类Models获取数据

→ 模板Template渲染

→ 再次经过Django中间件返回

→ uWSGI服务器将Response返回给Web服务器

→ Web服务器响应客户端的HTTP请求。

这其中耗时最多的2个环节通常是视图中业务逻辑处理和从Models获取数据(SQL查询),对于相同目的请求,也就是业务处理逻辑和SQL查询的数据都一样的请求,每次都进行了重复的计算,并且数据是从硬盘读取而非内存。

所以使用缓存有如下好处:

  • 降低服务器负载
  • 避免重复计算
  • 提高系统性能

二、如何进行缓存

很简单,一个Request请求过来,先去缓存中查询,有就返回;没有就去数据库查询并处理,然后把结果缓存好(供下次请求使用),再返回。用伪代码解释的话就是这样

三、缓存的类型

1. Memcached 效率最高,最快的缓存
2. Database caching 数据库缓存,这个指把数据缓存到数据表,比如你项目中使用的MySQL,就在MySQL中建表来专门缓存数据。不是指用Redis数据库
3. Filesystem caching 文件系统缓存,将缓存会把键值存储到独立的文件中去
4. Local-memory caching 使用系统内存缓存
5. Dummy caching (for development) 假缓存,只在开发过程中使用,以调试缓存接口,数据并没有真正缓存
6. Using a custom cache backend 自定义缓存后端,比如使用Redis

那么问题来了,我该使用哪种缓存呢?

其实常用的也就2种:Memcached或者Reids,其它基本不用考虑了。Redis国内用得多,支持RDB和AOF两种持久化方式,支持高可用集群,技术和方案很成熟,比如我的Django高级实战课程 https://coding.imooc.com/class/333.html,使用就是Redis缓存,将业务数据,Django channels,Celery任务分别缓存到4个不同的Redis库,甚至可以做成Redis集群的方式。而Memcached是纯内存存储,本身不支持持久化,不支持分布式,但是它内存管理效率高。

四、缓存粒度分类

  1. Per-site cache 把整个网站都缓存了,只需要在项目中设置加入缓存中间键的配置,系统便会自动对整个网站进行缓存
  2. Per-view cache 缓存某个视图
  3. Template fragment caching 模板的片段,比如Django模板继承base.html,通常是不变的导航栏
  4. Low-level cache API 低级别缓存API,比如缓存某个函数的结果,或者某个API接口

那么问题又来了,项目中我该选择什么样的缓存粒度?

是否需要缓存很简单,看内容是否变化。如果整个视图的数据通常都不变,就使用视图缓存,某些模板片段的数据不变就使用模板片段缓存等等。所以一个项目里面多种缓存粒度都有的,在Django高级实战课程 <https://coding.imooc.com/class/333.html里面使用到了per-view cache, Template fragment caching, low-level cache API三种,给大家帖一页PPT

五、Django缓存设置

这里只说一下Redis和Memcached的,其它很少用的就不罗列了,需要注意的是系统上要安装对应的缓存服务,Django开发环境中要安装连接缓存服务的包(比如django-redis或pymemcache)

  1. Memcache缓存设置

最简单的,配置地址和端口,不一定是要在本机,也可以是其它网段的服务器或集群

在本机的话,也可以使用unix Socket

也可以使用多态服务器,不同端口缓存

  1. Redis缓存设置

截图一下实战课程中Redis缓存的配置,缓存网站的数据

Django channels频道层的缓存

Celery缓存,broker和任务的执行结果

六、缓存的使用

对于Django项目缓存的数据,我们取出来或存进去操作,可以不需要直接操作底层的缓存数据,比如使用原生的Redis或Memcached命令,只需要使用Django提供的缓存API即可。就像我们使用Django ORM一样,无需关注底层数据库是MySQL, PostgreSQL或SQLite,ORM语句都一样。

例如,访问缓存

使用缓存

除了set(), get()还有get_or_set(), get_many(), set_many(), delete(), delete_many(), clear(), touch(), incr(), decr(), close()操作。大家可以去看看官网文档一个个操作下,要注意的是有的API不是每一个Django版本都有,比如cache.touch()是Django 2.1版本才有的。

七、Django缓存优化性能评估

缓存使用了,那效果怎么样,有什么指标可以衡量?用什么工具来衡量?

  1. Django Debug Toolbar

django-debug-toolbar是一个开源的工具,可以在看板上展示django对request/response处理的详细信息,比如当前请求响应的CPU耗时,settings/headers/request信息,当前请求使用的模板文件,静态文件,具体SQL语句和执行时间等等,看板要显示什么信息是可以灵活配置的。

在Django高级实战课程 <https://coding.imooc.com/class/333.html中,第12章 - 网站优化部分讲解了django-debug-toolar的时候,用来评估缓存优化,ORM语句和SQL优化的效果,如图:

右边的栏目就是django-debug-tool的看板

此页面共有9次SQL查询,耗时8.62毫秒

缓存命中3次,cache.get(),用时约0.91毫秒

  1. Jmeter压力测试

django-debug-tool是开发人员用,从功能角度测试缓存效果。而Jmeter就是专门测试人员用的,用于性能测试和压力测试。项目使用缓存后,整体性能是不是提高了,高负载情况下系统稳定性怎么样。测试方面的知识就不具体展开了,看慕课上有关于Jemeter的免费课,有兴趣的同学可以去看一下。

OK,今天的分享就到这里,关于Django项目缓存的,欢迎同学们提问,回头我把大家的问题和回答整理成文档发到群里。Bye~

用户提问:

  1. 缓存问题,有数据更新的时候是先写数据库还是先写缓存?脏读问题、或者先删缓存多线程又访问了,发现没有缓存又重新添加了缓存

【答】优先考虑先更新数据库,再删除缓存。关于缓存更新设计,当有数据更新的时候,你是打算更新缓存的数据,还是淘汰(删除)缓存的数据,所有就有了3种策略(没有先更新缓存,再更新数据库这种策略)。由于DB和Cache属于2个不同的系统,不能保证事务性的操作,一定涉及“哪个任务先做,哪个任务后做”的问题,解决这个问题的方向是:如果出现不一致,谁先做对业务的影响较小,就谁先执行。

  • 先删除缓存,再更新数据库

    低并发场景下,先删除缓存,更新数据库后,后续读操作会从数据库读取数据并更新缓存,仅会造成一次缓存未命中;

    低并发场景下,先删除缓存,更新数据库后,后续读操作会从数据库读取数据并更新缓存,仅会造成一次缓存未命中;
  • 先更新数据库,再更新缓存

    假设两个写线程T1、T2并发更新某一数据,T1先获取锁、更新数据库并且释放锁,T2获取锁、更新数据库然后释放锁;接下来T2更新缓存值,T1更新缓存值,这时候缓存中的数据T1为脏数据。
  • 先更新数据库,再删除缓存

    缓存数据失效的瞬间,读线程T1未命中缓存,然后到数据库取数据,取完数据后来了个写线程T2,T2先往数据库写数据,然后删除缓存,接着T1再把读到的老数据加载到缓存,此时也会造成脏读。这个情况出现的概率非常低,需要缓存失效的瞬间有并发的读写操作。而且数据库的写会比读慢很多,并且需要对数据加锁,所以T1必须在T2之前进入数据库进行操作,又要晚于T2更新缓存,所有这些条件都具备的概率非常低。

··················

作者:Jack

链接:https://www.imooc.com/article/291142

来源:慕课网

本文首次发布于慕课网 ,转载请注明出处,谢谢合作

Django项目缓存优化的更多相关文章

  1. django缓存优化中caches参数如何配置?

    在python开发中,如果运营django进行编写,为了提升效率,常常需要优化缓存,缓存优化中必须掌握的caches参数相关知识: CACHES 配置参数概述 - 格式 CACHES 字典配置格式如下 ...

  2. django项目环境搭建

    本文转载自: https://blog.csdn.net/xiaogeldx/article/details/89038299 在码云平台创建项目 版本控制的种类 主要使用github(最主流) 国内 ...

  3. django项目的配置文件settings.py详解

    我们创建好了一个Python项目(mysite/)之后,需要在项目中添加模块应用(polls/),在模块应用中添加处理功能逻辑,如添加模块中的视图处理函数(polls.views.index()),这 ...

  4. 【5】Django项目配置settings.py详解

    夫唯不争,故天下莫能与之争 --老子<道德经> 本节内容 1.项目配置文件settings.py介绍 2.数据库配置[MySQL] 3.创建模型对象并和数据库同步 4.python官方提供 ...

  5. Django项目纪要

    开发流程 公司高层 项目立项 | 市场部门 需求分析-->需求分析说明书, 需求规格说明书 | 产品部门 产品原型-->产品 UI 前端 后端 测试 移动端 | |------------ ...

  6. Django后台缓存运用,提高并发

    图片防盗链 -通过请求头refer控制 -nginx处理 提高网站并发的通用方法 QPS:每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准.衡量一个服务器能抗多大并发的重要 ...

  7. [译]如何使用 Docker 组件开发 Django 项目?

    原文地址:Django Development With Docker Compose and Machine 以下为译文 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包 ...

  8. iOS网络加载图片缓存策略之ASIDownloadCache缓存优化

    iOS网络加载图片缓存策略之ASIDownloadCache缓存优化   在我们实际工程中,很多情况需要从网络上加载图片,然后将图片在imageview中显示出来,但每次都要从网络上请求,会严重影响用 ...

  9. Nginx+uWSGI或fastcgi部署Django项目

    nginx+uWSGI ubuntu下先安装下C编译器和Python环境: sudo apt-get install build-essential python-dev 使用pip安装uWSGI: ...

  10. MySQL优化二(连接优化和缓存优化)

    body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-top: 10 ...

随机推荐

  1. js原型和原型链(用代码理解代码)

    众所周知js原型及原型链是很多开发者的一个疼点(我也不例外),我也曾多次被问起,也问过不少其他人,如果在自己没有真正的去实践和理解过:那么突然之间要去用最简单的话语进行概述还真不是一件容易的事情: 其 ...

  2. Charles一文全明白

    自从用上了Mac本,抓包工具也从Fiddler换成了Charles,用了这么长时间,也是该对Charles做一个总结了,避免自己下次配置的时候又忘记怎么操作 1.Charles是什么? Charles ...

  3. 神经网络初步(Neural Network)——思想 具体实例以及代码实现

    在前面我们详细的讨论过softmax损失函数以及SVM损失函数,以及应用了支持向量机进行图片分类的任务,不妨先复习一下支持向量机相关的思想内核:支持向量机想要寻求一组映射关系f(x)=wx+b,先将每 ...

  4. STL-priority_queue(ACM)

    1.无法访问v.front().v.back() 2.是一个 堆,默认为大根堆,改造后为小根堆 大根堆 重构函数(默认)(大根堆) priority_queue<int> v; 基本操作 ...

  5. 「AntV」L7地理可视化:从入门到实践

    1. 前言 这是一篇由浅入深的AntV L7的学习笔记总结,记述了从了解到使用的一些过程 本文所使用的数据(包括数据处理过程)和代码均有详细描述,所有案例均可复现,甚至大部分代码可直接使用 如果喜欢分 ...

  6. 【HMS Core】Health Kit云测数据接入相关问题

    ​[问题描述1] 1.由于存在IOS.android.微信小程序,计划接入"云侧数据开放服务",使用模式为我们自己的服务端去同步华为健康数据,终端通过服务端获取最新的数据. 2.在 ...

  7. ARC114F Permutation Division

    题意 给定一个 \(1 \sim N\) 的排列,Alice 把它划分成 \(k\) 段,Bob 把这 \(k\) 段任意排列.Alice 想让字典序最小,Bob 想让字典序最大.请问最后的排列. 数 ...

  8. 2023-06-24:给你一根长度为 n 的绳子, 请把绳子剪成整数长度的 m 段, m、n都是整数,n > 1并且m > 1, 每段绳子的长度记为 k[0],k[1]...k[m - 1]。 请问

    2023-06-24:给你一根长度为 n 的绳子, 请把绳子剪成整数长度的 m 段, m.n都是整数,n > 1并且m > 1, 每段绳子的长度记为 k[0],k[1]...k[m - 1 ...

  9. [ARM 汇编]高级部分—ARM汇编编程实战—3.3.2 嵌入式开发环境搭建

    搭建一个嵌入式开发环境主要包括以下几个部分: 安装交叉编译器 配置集成开发环境(IDE) 安装调试工具 下载和烧录程序 接下来,我们将详细介绍每个部分,并提供相应的实例. 安装交叉编译器 交叉编译器是 ...

  10. Github的一个彩蛋

    点击新建仓库 项目名称为自己的昵称 下方提示意思说: 你发现了一个秘密 这是一个特别的仓库 你可以为你的首页增加README.md 就像给项目介绍一样,这是你的自我介绍 点击编辑,里面会与建议模板 以 ...