《Django中使用Redis进行缓存》要点:
本文介绍了Django中使用Redis进行缓存,希望对您有用。如果有疑问,可以联系我们。
Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发.
应用程序的性能对于你的产品的成功与否显得至关重要.在用户想要网站在不到一秒1s的时间里响应的情况下,一个缓慢的应用程序就可以造成金钱上的损失.就算你没有在销售什么东西,更快的页面加载也会改善使用体验.
所有在服务器收到数据和作出响应之间发生的事情都会延长页面加载时间.照经验来说,在服务器省略越多的步骤,你的应用程序跑的就越快.在数据被处理后将其缓存并在下一次请求时直接拿出来是减轻服务器压力的一种方法.在这篇教程里,我们来研究一下拖慢你应用程序速度的因素,再演示怎样用Redis实现缓存来抵消那些因素的作用效果.
什么是Redis?
Redis是一个可以用来作为缓存引擎的基于内存的数据结构存储.既然它在内存中存储数据,那么速度一定很快.Redis不是唯一可以用来作为缓存的产品.Memcached便是另一款出名的基于内存的缓存系统,但很多人认为在大多数情况下Redis比Memcached更优秀.个人来说,我们喜欢它的设置简单以及还可以用于其他用途,比如说Redis Queue.
开始
我们创建了一个示例应用程序来向你介绍缓存的概念.我们的程序使用:
Django (v1.9.8
Django Debug Toolbar (v1.4
django-redis (v4.4.3
Redis (v3.2.0
安装这个程序
在你克隆仓库之前,先安装virtualenvwrapper,如果你还没有的话.这个工具让你安装你的项目需要的特定的Python依赖,并允许你定位你的app需要的版本和库.
接下来,把目录切换到你保存项目的地方再克隆示例程序仓库.完成以后,把目录切换进去,再用 mkvirtualenv 命令为示例程序创建一个新的虚拟环境:
注意:用 mkvirtualenv 命令创建一个虚拟环境也就同时把它激活了.
用 pip安装所有需要的Python依赖,再检查一下下面的标签:
通过构建数据库并向其中填入样本数据来结束示例程序的设置.别忘了创建一个超级用户,这样你才能登陆管理站点.跟随下面的示例代码再试试运行程序,确保它能正常工作.在浏览器里进入管理页确认一下数据是否正常加载.
当你的Django程序运行起来后,就去安装Redis.
安装Redis
按照文档里提供的步骤下载安装Redis.或者,你也可以用一个包管理器来安装Redis,比如说 apt-get或者homebrew,具体取决于你的操作系统.
在一个新的终端窗口中启动Redis服务:
接下来,在另一个终端窗口启动Redis命令行接口(CLI),测试一下是否连接到了Redis Server. 我们会用Redis CLI来检查添加到缓存中的键.
Redis提供了一个有着多种命令的API,开发者可以用来操作数据存储.Django使用 django-redis来在Redis里执行命令.
在一个文本编辑器里查看我们的示例程序,我们可以在 settings.py里看到Redis配置.我们在CACHES里定义了一个默认缓存,用内置的 django-redis 作为后端.Redis默认在6379端口运行,我们在设置里指出这个端口.最后要指出的是,django-redis附加了带有前缀和版本的键名来区分相似的键.所以我们把前缀定义为 "example".
注意:虽然我们配置了缓存后端,但是还没有一个视图函数真正实现缓存.
程序性能
在这篇文章开头我们就曾提到,服务器处理一个请求所做的所有事情都会延长程序加载时间.运行业务逻辑和呈现模板的处理开销可能很大.网络潜在因素也会影响查询数据库的时间.每当一个客户端向服务器发送一个HTTP请求时,这些因素都会出现.当用户每秒发起多个请求时,由于服务器要处理所有请求,性能的影响将变得明显.
当我们实现缓存时,我们让服务器处理一次请求,然后将它存储在缓存中.当我们的应用程序接收到相同URL的请求时,服务器就直接从缓存中提取结果,而不是每次都重新处理它们. 通常,我们会设置缓存结果的存活时间,以便可以定期刷新数据,这是实现缓存的一个重要步骤,以避免提供过时的数据.
您应该考虑在以下情况存在时缓存请求的结果:
呈现页面涉及到大量数据库查询和/或业务逻辑.
页面经常被你的用户访问.
每个用户的数据是相同的.
数据不经常变化.
从测量性能开始
首先,通过衡量应用程序在收到请求后的响应速度来测试应用程序中每个页面的速度.
为了实现这一点,我们使用loadtest,一个HTTP负载生成器,用大量的请求来“轰炸”每个页面,再密切关注请求速率.点击上面的链接安装.安装好后,根据/cookbook/URL路径测试结果.
注意到我们每秒钟处理16个请求:
当我们看见代码在干什么的时候,我们就可以决定怎样作出改动来改善性能.该应用程序向一个数据库发出3个网络调用请求 /cookbook/,并且每次调用都需要时间打开一个连接并执行查询.在你的浏览器里访问/cookbook/URL并展开Django Debug工具栏选项卡以确认此行为.找到名为“SQL”的标签再看看查询的数目.
cookbook/services.py
cookbook/views.py
这个应用程序还会渲染一个有着潜在的开销巨大的逻辑的模板.
实现缓存
想象一下当用户访问我们的网站时我们的应用程序会发出的网络调用的总数.如果1000个用户调用获取cookbook的API,我们的程序就会进行3000次数据库查询,并且每次请求都会渲染一个新模板.这个数字会随着应用程序规模的增长而曾长.幸好,这个视图是用于缓存的不二之选.cookbook里的食谱很少变化.再说,既然app的中心作用是读取cookbook,那么获取食谱的API一定会被经常调用.
在下面的例子中,我们改变了视图函数以使其使用缓存.当函数工作时,它会检查视图键是否在缓存中.如果键存在的话,app就从缓存读取数据并返回.如果不在的话,Django就会查询数据库并将其和视图键存储在缓存中.函数第一次被调用时,Django会查询数据库并渲染模板,再向Redis发起网络调用将数据存进缓存.随后的函数调用将会完全绕过数据库和业务逻辑并直接查询Redis缓存.
注意我们向视图函数添加了一个装饰器 @cache_page,还添加了一个生存时间.再访问一下/cookbook/并检查Django Debug 工具栏.我们看到进行了3次数据库查询,并对缓存进行了3次调用,以便检查键,然后保存它.Django保存两个键(一个键用于标题,一个用于呈现的页面内容).重新加载页面看看页面活动怎样变化的.第二次,数据库调用0次,缓存调用两次.我们的页面现在是缓存提供的!
当我们重新运行性能测试时,我们看到我们的程序加载更快了.
缓存提高了总负载量,我们现在每秒解析21个请求,比我们的基准多了5个.
用CLI检查Redis
这时候我们可以用Redis CLI看看Redis Server上存了些什么.在Redis命令行中,输入命令 keys *,这会返回满足任何模式的键.你应该会看到一个叫“example:1:views.decorators.cache.cache_page”的键.别忘了,“example”是我们的键前缀,“1”是版本,“views.decorators.cache.cache_page”是Django给键的名字.把键名复制下来输在get命令后面.你可以看到已渲染的HTML代码.
注意:在Redis CLI运行 flushall 命令来从数据存储里清除所有的键,然后你可以重新过一遍这个教程,不用等缓存过期了.
总结
处理HTTP请求的代价是昂贵的,并且会随着你的应用程序的数量增长而增加.有的情况下,实现缓存会极大地减少服务器的处理量.这篇教程涉及了在Django中用Redis实现缓存的一些基本点,略过了一些复杂的主题.在一个健壮的程序里实现缓存有很多陷阱.控制哪些数据被缓存和存活期有多长很困难.缓存失效是计算机科学中一件棘手的事情.保证私有数据只能被特定的用户访问是个安全问题并且需要在缓存时仔细处理.在示例程序中去玩转源码,并且在你继续用Django开发的时候,要常记着考虑性能.
英文原文:https://realpython.com/blog/python/caching-in-django-with-redis/
欢迎参与《Django中使用Redis进行缓存》讨论,分享您的想法,维易PHP学院为您提供专业教程。