Django—— 缓存框架

译者注:1、无用的,吹嘘的说辞不翻译;2、意译,很多地方不准确。

动态网站最为重要的一点就是好,网页是动态的。每一次用户请求页面,网站就要进行各种计算——从数据库查询,到render模板,到各种逻辑运算——生成页面所需的。这个过程是异常消耗资源的,远远比从硬盘读取一个文件然后显示出来的代价高昂。

对于大多数中小网站来说,这也许不是问题,因为他们的访问量不大,而对于大型网站而言,必须尽量减少不必要的服务器资源开支。

因此,有了缓存技术。

缓存就是把一些需要消耗很多资源的计算结果保存下来,当下次需要时,不需要再次进行计算,直接从缓存中取,从而节省了资源。缓存的伪码表达如下:

给定的url,在缓存中查找是否存在;

如果存在,返回cached page;

否则:

生成该页面;

把该页面保存在缓存中

return 页面

django的缓存系统非常健壮…..(一些自夸的话,译者注)。简单的说,django提供不同粒度的缓存:特定view的缓存,缓存某个耗时的程序片段的结果,或者缓存整个网站。

django也能够和一些“上游的”缓存技术协同工作,例如squid ,浏览器的缓存等。这些缓存类型是你不需要直接控制,但是可以通过HTTP head 协议来告诉别人,网站的那些部分需要被缓存,如何缓存。

建立缓存

缓存系统(cache system)需要一些设置。你需要告诉django,你的缓存数据保存在什么地方:文件,数据库,或者内存中。不同的缓存方式的性能是不同的。

在settings.py文件中,设置CACHE_BACKEND, 下面是一些可用的CACHE_BACKEND值:

Memcached

目前最快的,效率最高的cache。

Memcached的官方网站:http://danga.com/memcached/  Memcached的所有数据都存在内存中,因此,不会有数据库消耗和读取文件消耗。

安装Memcached后,你需要安装Memcached python bindings。目前有两种版本可用,分别为:

速度最快的选择是cmemcache,下载地址为 http://gijsbert.org/cmemcache/

django 1.0之前版本不可用。

如果你无法安装 cmemcache, 你可以选择安装 python-memcached, 下载地址:ftp://ftp.tummy.com/pub/python-memcached/ . 如果这个网址已经失效,, 到memcached官方网站 (http://www.danga.com/memcached/) ,到“Client APIs”下载 Python bindings.

使用Memcached,只需把CACHE_BACKEND设置为memcached://ip:port/的格式,ip地址是memcached服务运行的机器ip地址,端口是memcached服务监听的端口号。

示例如下,如果memcached服务运行于本机,端口为11211,则配置语句为:

CACHE_BACKEND=’memcached://127.0.0.1:11211/’

memcached一个非常好的特性是可以多机共享cache,只需把所有提供缓存的机器的ip地址和端口号全部列入即可,之间用逗号分开。示例如下:

CACHE_BACKEND= ‘memcached://172.19.26.240:11211;172.19.26.242:11211/’

memcache也许有一个缺点,那就是由于memcached是基于内存的,当你的服务器crash时,所有的cache数据都将丢失。但由于cache本身就是临时的,所以,丢失cache数据没什么大问题。

翻译:django 缓存框架(2)(django cache framework)[转载]

January 17, 2009 by admin · Leave a Comment
Filed under: django

在网络上搜索了一下,这篇文章已经有人翻译过了。

原文在这里:http://www.woodpecker.org.cn/obp/django/django-faq/cache.html

文件系统缓存

要在文件系统中保存缓存数据, 在 CACHE_BACKEND 中使用 “file://” 缓存类型. 下面这个例子将缓存数据保存在 /var/tmp/django_cache 中, 设置如下:

CACHE_BACKEND = ‘file:///var/tmp/django_cache’

注意 file: 之后是三个斜线而不是两个. 前两个是 file:// 协议, 第三个是路径 /var/tmp/django_cache 的第一个字符.

这个目录路径必须是绝对路径 — 也就是说,它应该从你的文件系统的根开始算起.至于路径的最后是否加一个斜线, Django 并不在意.

要确保这个设定的路径存在并且 Web 服务器可以读写.继续上面的例子,如果你的服务器以 apache 用户身份运行, 确保目录 /var/tmp/django_cache 存在并且可以被用户 apache 读写.

本地内存缓存

如果你想要内存缓存的高性能却没有条件运行 Memcached, 可以考虚使用本地内存缓存后端. 这个缓存后端是多进程的并且线程安全. 要使用它,设置 CACHE_BACKEND 为 “locmem:///”. 举例来说:

CACHE_BACKEND = ‘locmem:///’

简单缓存(用于开发)

“simple:///” 是一个简单的,单进程的内存缓存类型. 它仅仅在进程中保存缓存数据, 这意味着它仅适用于开发或测试环境. 例子:

CACHE_BACKEND = ’simple:///’

虚拟缓存 (用于开发)

最后, Django还支持一种 “dummy” 缓存(事实上并未缓存) — 仅仅实现了缓存接口但未实际做任何事.

CACHE_BACKEND 参数

所有缓存类型均接受参数. 提供参数的方式类似查询字符串风格. 下面列出了所有合法的参数:

timeout

默认的缓存有效时间,以秒计. 默认值是 300 秒(五分钟).

max_entries

用于 简单缓存 及 数据库缓存 后端, 缓存的最大条目数(超出该数旧的缓存会被清除,默认值是 300).

cull_percentage

当达到缓存的最大条目数时要保留的精选条目比率. 实际被保存的是 1/cull_percentage, 因此设置 cull_percentage=3 就会保存精选的 1/3 条目上,其余的条目则被删除.

如果将 cull_percentage 设置为 0 则意味着当达到缓存的最大条目数时整个缓存都被清除.当缓存命中率很低时这会 极大的 提高精选缓存条目的效率(根本不精选).

这个例子里, timeout 被设置为 60:

CACHE_BACKEND = “memcached://127.0.0.1:11211/?timeout=60″

这个例子, timeout 设置为 30 而 max_entries 设置为 400:

CACHE_BACKEND = “memcached://127.0.0.1:11211/?timeout=30&max_entries=400″

非法的参数会被忽略.

缓存整个站点

设置了缓存类型之后, 最简单使用缓存的方式就是缓存整个站点. 在“MIDDLEWARE_CLASSES“ 设置中添加 django.middleware.cache.CacheMiddleware , 就象下面的例子一样:

MIDDLEWARE_CLASSES = (

”django.middleware.cache.CacheMiddleware”,

”django.middleware.common.CommonMiddleware”,

)

( MIDDLEWARE_CLASSES 顺序相关. 参阅下文中的 “Order of MIDDLEWARE_CLASSES”)

然后,在 Django 设置文件中添加以下设置:

CACHE_MIDDLEWARE_SECONDS — 每个页面被缓存的时间.

CACHE_MIDDLEWARE_KEY_PREFIX — 如果缓存被同一个 Django 安装的多个站点共享, 在这里设置站点名字, 或者某些其它唯一的字符串, 以避免 key 冲突.如果你不介意,也可以使用空串.

缓存中间件缓存没有 GET/POST 参数的每个页面.另外, CacheMiddleware 自动在每个 HttpResponse 中设置一些 headers:

当请求一个未缓存页面时,设置 Last-Modified header 到当前的日期时间.

设置 Expires header 到当前日期时间加上定义的 CACHE_MIDDLEWARE_SECONDS.

设置 Cache-Control header 为该页面的生存期 — 该生存期也来自 CACHE_MIDDLEWARE_SECONDS 设置.

参阅 middleware documentation 了解中间件的更多信息.

缓存单个 view

Django 能够只缓存特定的页面. django.views.decorators.cache 定义了一个 cache_page 修饰符, 它能自动缓存该 view 的响应. 该修饰符的使用极为简单:

from django.views.decorators.cache import cache_page

def slashdot_this(request):

slashdot_this = cache_page(slashdot_this, 60 * 15)

或者, 使用Python 2.4 的修饰符语法:

@cache_page(60 * 15)

def slashdot_this(request):

cache_page 仅接受一个参数: 缓存有效期,以秒计. 在上面的例子里,  slashdot_this() view 将被缓存 15 分钟.

底层缓存 API

某些时候, 缓存一个完整的页面不符合你的要求. 比如你认为仅有某些高强度的查询才有必要缓存其结果.要达到这种目的,你能使用底层缓存 API 来在任意层次保存对象到缓存系统.

缓存 API 是简单的. 从缓存模块 django.core.cache 导出一个由 CACHE_BACKEND 设置自动生成的 cache 对象:

>>> from django.core.cache import cache

基本的接口是 set(key, value, timeout_seconds) 和 get(key):

>>> cache.set(’my_key’, ‘hello, world!’, 30)

>>> cache.get(’my_key’)

‘hello, world!’

timeout_seconds 参数是可选的,其默认值等于 CACHE_BACKEND 的 timeout 参数.如果缓存中没有该对象, cache.get() 返回 None:

>>> cache.get(’some_other_key’)

None

# Wait 30 seconds for ‘my_key’ to expire…

>>> cache.get(’my_key’)

None

get() 可以接受一个 default 参数:

>>> cache.get(’my_key’, ‘has expired’)

‘has expired’

当然还有一个 get_many() 接口, 它仅仅命中缓存一次. get_many() 返回一个字典,包括未过期的实际存在的你请求的所有键.:

>>> cache.set(’a‘, 1)

>>> cache.set(’b‘, 2)

>>> cache.set(’c‘, 3)

>>> cache.get_many([‘a‘, ‘b‘, ‘c‘])

{’a‘: 1, ‘b’: 2, ‘c’: 3}

最后, 你可以使用  delete() 显式的删除键. 这是一个在缓存中清除特定对象的简便的方式:

>>> cache.delete(’a‘)

就是这样. 缓存机制限制非常少: 你可以安全的缓存能被 pickled 的任意对象(key必须是字符串).

Upstream caches

到现在为止, 我们的目光仅仅聚焦在 你自己的 数据上. 在 WEB 开发中还有另外一种类型的缓存:

“upstream” 缓存. 这是用户请求还未抵达你的站点时由浏览器实施的缓存.

下面是 upstream 缓存的几个例子:

你的 ISP 会缓存特定页面, 当你请求 somedomain.com 的一个页面时, 你的 ISP 会直接发送给你一个缓存页.(不访问 somedomain.com ).

你的 Django Web 站点可能建立在一个 Squid (http://www.squid-cache.org/) Web
代理服务器之后, 它会缓存页面以提高性能. 这种情况下,每个请求会先经 Squid 处理, 仅在需要时它会将请求传递给你的应用程序.

你的浏览器也会缓存一些页面. 如果一个 WEB 页发送了正确的 headers, 浏览器会用本地(缓存的)拷贝来回应后发的同一页面的请求.

Upstream 缓存是一个非常有效的推进, 不过它也有相当不足之处: 很多 WEB 页基于授权及一堆变量, 而这个缓存系统盲目的单纯依赖 URL 缓存页面, 这可能会对不适当的用户泄露敏感信息.

举例来说,假设你使用一个 Web e-mail 系统, “inbox” 页的内容显然依赖当前登录用户. 如果一个 ISP 盲目的缓存了你的站点, 后来的用户就会看到前一用户的收件箱, 这可不是一件有趣的事.

幸运的是, HTTP 提供了一个该问题的解决方案: 用一系列 HTTP headers 来构建缓存机制以区分缓存内容, 这样缓存系统就不会缓存某些特定页.

使用 Vary headers

其中一个 header 就是 Vary. 它定义了缓存机制在创建缓存 key 时的请求 headers. 举例来说, 如果一个网页的内容依赖一个户的语言设置, 则该网页被告知 “vary on language.”

默认情况, Django 的缓存系统使用请求路径创建 缓存 key —
比如, ”/stories/2005/jun/23/bank_robbed/”. 这意味着该 URL 的每个请求使用相同的缓存版本,
不考虑用户代理的不同.(cookies 及语言特性).

因此我们需要 Vary .

如果你的基于 Django 的页面根据不同的请求 headers 输出不同的内容 — 比如一个 cookie, 或语言, 或用户代理 — 你会需要使用 Vary header 来告诉缓存系统这个页面输出依赖这些东西.

要在 Django 中做到这一步, 使用  vary_on_headers view 修饰符,就象下面这样:

from django.views.decorators.vary import vary_on_headers

# Python 2.3 syntax.

def my_view(request):

my_view = vary_on_headers(my_view, ‘User-Agent’)

# Python 2.4 decorator syntax.

@vary_on_headers(’User-Agent’)

def my_view(request):

这样缓存系统 (比如 Django 自己的缓存中间件) 会为不同的用户代理缓存不同的版本的页面.使用 vary_on_headers
修饰符的优势在于(与人工设置 Vary header 相比:使用类似 response[‘Vary‘] =
‘user-agent’)修饰符会添加到 Vary header (可能已存在) 而不是覆盖掉它.

你也可以传递多个 header 给 vary_on_headers():

@vary_on_headers(’User-Agent’, ‘Cookie’)

def my_view(request):

由于多个 cookie 的情况相当常见, 这里有一个 vary_on_cookie 修饰符. 下面两个 views 是等价的:

@vary_on_cookie

def my_view(request):

@vary_on_headers(’Cookie’)

def my_view(request):

需要注意一点传递给 vary_on_headers 的参数是大小写不敏感的. “User-Agent” 与 “user-agent” 完全相同.

你也可以直接使用一个帮助函数, django.utils.cache.patch_vary_headers:

from django.utils.cache import patch_vary_headers

def my_view(request):

response = render_to_response(’template_name’, context)

patch_vary_headers(response, [‘Cookie‘])

return response

patch_vary_headers 接受一个 HttpResponse 实例作为它的第一个参数及一个 header 名字的列表或tuple作为第二个参数.

要了解 Vary headers 的更多信息, 参阅 official Vary spec.

控制缓存: 使用其它 headers缓存的另一个问题是数据的私密性及瀑布缓存模式下数据保存到哪里.

用户经常要面对的有两种缓存: 他自己的浏览器缓存(私人缓存) 及站点提供的缓存(公开缓存).一个公开缓存用于多用户情况,
其内容由另外的人控制. 这造成了数据的私密性问题: 你当然不想你的银行帐号保存在公共缓存里.
因此应用程序需要一种方式告诉缓存系统哪些东西是私密的,哪些则是公开的.

解决方案就是声明某个页面的缓存是 “私密的”. 在 Django 中, 使用 cache_control view 修饰符. 例子:

from django.views.decorators.cache import cache_control

@cache_control(private=True)

def my_view(request):

这个修饰符会在幕后谨慎的发送适当的 HTTP header 发避免上面的问题.

还有一些其它的方式控制缓存参数. 举例来说,HTTP 允许应用程序做以下事:

定义一个页面被缓存的最大时间.指定缓存是否需要总是检查新版本, 如果没有变化则仅传送缓存版本. (某些缓存即使服务器端页面变化也仅传递缓存版本–仅仅因为缓存拷贝尚未到期).

在 Django 中, 使用 cache_control view 修饰符指定缓存参数.在这个例子里 cache_control 通知缓存每次检验缓存版本, 直到 3600 秒到期:

from django.views.decorators.cache import cache_control

@cache_control(must_revalidate=True, max_age=3600)

def my_view(request):

所有合法的 Cache-Control HTTP 指令在 cache_control() 中都是合法的. 下面是完整的指令列表:

public=True

private=True

no_cache=True

no_transform=True

must_revalidate=True

proxy_revalidate=True

max_age=num_seconds

s_maxage=num_seconds

要了解 Cache-Control HTTP 指令的细节,参阅 Cache-Control spec.

(注意缓存中间件已经通过设置中的 CACHE_MIDDLEWARE_SETTINGS 的值设定了缓存 header 的 max-age.
如果你在 cache_control 修饰符中使用了自定义的 max_age , 修饰符中的设置将被优先使用, header 值会被正确的合并)

其它优化

Django 自带了一些中间件以帮助你提高站点性能:

django.middleware.http.ConditionalGetMiddleware 添加了有条件GET的支持. 它利用了 ETag 及 Last-Modified headers.

django.middleware.gzip.GZipMiddleware 为支持 Gzip 的浏览器对发送内容进行压缩(所有流行浏览器均支持).

MIDDLEWARE_CLASSES 顺序

如果你使用了 CacheMiddleware, 在 MIDDLEWARE_CLASSES 设置中使用正确顺序非常重要. 由于缓存中间件需要知道哪些 headers 由哪些缓存存储.中间件总是在可能的情况下添加某些东西到 Vary 响应 header.

将 CacheMiddleware 放到其它可能添加某些东西到 Vary Header的中间件之后,下面的中间件会添加东西到 Vary header:

SessionMiddleware 添加了 Cookie

GZipMiddleware 添加了 Accept-Encoding

时间: 2024-10-24 19:56:54

Django—— 缓存框架的相关文章

python Django Wbe框架教程

python  Django Wbe框架教程 一.简介 Django 中提供了开发网站经常用到的模块,常见的代码都为你写好了,通过减少重复的代码,Django 使你能够专注于 web 应用上有 趣的关键性的东西.为了达到这个目标,Django 提供了通用Web开发模式的高度抽象,提供了频繁进行的编程作业的快速解决方法,以及为“如何解决问题”提供了清晰明了的约定.Django的理念是DRY(Don't Repeat Yourself)来鼓励快速开发! 让我们一览 Django 全貌 urls.py

缓存框架Guava Cache部分源码分析

在本地缓存中,最常用的就是OSCache和谷歌的Guava Cache.其中OSCache在07年就停止维护了,但它仍然被广泛的使用.谷歌的Guava Cache也是一个非常优秀的本地缓存,使用起来非常灵活,功能也十分强大,可以说是当前本地缓存中最优秀的缓存框架之一.之前我们分析了OSCache的部分源码,本篇就通过Guava Cache的部分源码,来分析一下Guava Cache的实现原理. 在分析之前,先弄清数据结构的使用.之前的文章提到,OSCache使用了一个扩展的HashTable,作

缓存框架OSCache部分源码分析

在并发量比较大的场景,如果采用直接访问数据库的方式,将会对数据库带来巨大的压力,严重的情况下可能会导致数据库不可用状态,并且时间的消耗也是不能容忍的.在这种情况下,一般采用缓存的方式.将经常访问的热点数据提前加载到内存中,这样能够大大降低数据库的压力. OSCache是一个开源的缓存框架,虽然现在已经停止维护了,但是对于OSCache的实现还是值得学习和借鉴的.下面通过OSCache的部分源码分析OSCache的设计思想. 缓存数据结构 通常缓存都是通过<K,V>这种数据结构存储,但缓存都是应

5个强大的Java分布式缓存框架推荐

在开发中大型Java软件项目时,很多Java架构师都会遇到数据库读写瓶颈,如果你在系统架构时并没有将缓存策略考虑进去,或者并没有选择更优的缓存策略,那么到时候重构起来将会是一个噩梦.本文主要是分享了5个常用的Java分布式缓存框架,这些缓存框架支持多台服务器的缓存读写功能,可以让你的缓存系统更容易扩展. 1.Ehcache – Java分布式缓存框架 Ehcache是一个Java实现的开源分布式缓存框架,EhCache 可以有效地减轻数据库的负载,可以让数据保存在不同服务器的内存中,在需要数据的

Android轻量缓存框架--ASimpleCache

[转] 大神真面目 稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识.前端.后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过! 编辑推荐: 做Android应用开发的同学们相信对“缓存”这个词不陌生,缓存可能有多方面的概念,这里大概列举下程序开发的缓存大概有哪些: 1.服务端控制缓存 如volley请求库,便是通过服务端的“Cache-Control”和“max-age”来告诉客户端有没有缓存以及缓存的时间,也是推荐的使用

Java分布式缓存框架

http://developer.51cto.com/art/201411/457423.htm 在开发中大型Java软件项目时,很多Java架构师都会遇到数据库读写瓶颈,如果你在系统架构时并没有将缓存策略考虑进去,或者并没有选择更优的缓存策略,那么到时候重构起来将会是一个噩梦.本文主要是分享了5个常用的Java分布式缓存框架,这些缓存框架支持多台服务器的缓存读写功能,可以让你的缓存系统更容易扩展. 1.Ehcache – Java分布式缓存框架 Ehcache是一个Java实现的开源分布式缓存

mybatis0210 mybatis和ehcache缓存框架整合

1.1mybatis和ehcache缓存框架整合 一般不用mybatis来管理缓存而是用其他缓存框架在管理缓存,因为其他缓存框架管理缓存会更加高效,因为别人专业做缓存的而mybatis专业做sql语句的,mybatis二级缓存通过ehcache维护缓存数据. 1.1.1分布缓存 将缓存数据数据进行分布式管理.用户发起请求,首先会根据负载选择不同的服务器,如果用户在服务器1和服务器2都登录过,那么把用户的session分别放在服务器1和服务器2是不行的,所以就把用户的信息放在远程服务器集群中统一管

Java的进程内缓存框架:EhCache (转)

EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. Ehcache缓存的特点: 1. 快速. 2. 简单. 3. 多种缓存策略 4. 缓存数据有两级:内存和磁盘,因此无需担心容量问题 5. 缓存数据会在虚拟机重启的过程中写入磁盘 6. 可以通过RMI.可插入API等方式进行分布式缓存 7. 具有缓存和缓存管理器的侦听接口 8. 支持多缓存管理器实例,以及一个实例的多个缓存区域 9. 提供Hibernate的缓存实现 E

Java缓存框架

JBossCache/TreeCache JBossCache是一个复制的事务处理缓存,它允许你缓存企业级应用数据来更好的改善性能.缓存数据被自动复制,让你轻松进行Jboss服务器之间的集群工作.JBossCache能够通过Jboss应用服务或其他J2EE容器来运行一个Mbean服务,当然,它也能独立运行. JBossCache包括两个模块:TreeCache和TreeCacheAOP. TreeCache --是一个树形结构复制的事务处理缓存. TreeCacheAOP --是一个“面向对象”