Django框架认知:自带强大的缓存系统

2023-06-1819:08:51后端程序开发Comments963 views字数 8150阅读模式

动态网站的一个基本取舍是,它们是动态的。每当用户请求一个页面时,网络服务器都会进行各种计算 —— 从数据库查询到模板渲染再到业务逻辑 —— 以创建访客看到的页面。从处理花费的角度来看,这比标准的从文件系统中读取文件的服务器安排要昂贵得多。对于中高流量的网站来说,必须尽可能地减少开销。这就是缓存的用武之地。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

缓存就是将昂贵的计算结果保存下来,这样下次就不用再进行计算了。以下是一些伪代码,解释了如何在动态生成的网页中使用这种方法:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

given a URL, try finding that page in the cacheif the page is in the cache: return the cached pageelse: generate the page save the generated page in the cache (for next time) return the generated page文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

Django 自带强大的缓存系统,可以让动态页面不必为每次请求计算。为了方便,Django 提供了不同级别的缓存粒度。可以缓存特定视图,只缓存难以生成的部分,或者缓存整个网站。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

设置缓存

缓存系统需要少量的设置。也就是说,你必须告诉它你的缓存数据应该放在哪里 —— 是在数据库中,还是在文件系统上,或者直接放在内存中。这是一个重要的决定,会影响你的缓存的性能;是的,有些缓存类型比其他类型快。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

缓存设置项位于你的配置文件的缓存配置中。这里有缓存配置所有可用值的说明。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

Memcached

Memcached 是一个完全基于内存的缓存服务器,是 Django 原生支持的最快、最高效的缓存类型,最初被开发出来用于处理 LiveJournal.com 的高负载,随后由 Danga Interactive 开源。Facebook 和 Wikipedia 等网站使用它来减少数据库访问并显著提高网站性能。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

Memcached 以一个守护进程的形式运行,并且被分配了指定数量的 RAM。它所做的就是提供一个快速接口用于在缓存中添加,检索和删除数据。所有数据都直接存储在内存中,因此不会产生数据库或文件系统使用的开销。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

在安装了 Memcached 本身之后,你需要安装一个 Memcached 绑定。有几个 Python Memcached 绑定可用;Django 支持的两个绑定是 pylibmc 和 pymemcache 。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

在 Django 中使用 Memcached :文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

  • 设置BACKEND 为 django.core.cache.backends.memcached.PyMemcacheCache 或 django.core.cache.backends.memcached.PyLibMCCache (取决于你选择的 memcached 绑定)。
  • 将 LOCATION 设置为 ip:port 值,其中 ip 是 Memcached 守护进程的 IP 地址,port 是 Memcached 运行的端口,或者设置为 unix:path 值,其中 path 是 Memcached Unix socket 文件的路径。

Memcached 运行在 localhost(127.0.0.1)端口 11211,使用 pymemcache 绑定:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

CACHES = {    'default': {        'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',        'LOCATION': '127.0.0.1:11211',    }}

Memcached 可以通过本地 Unix 套接字文件 /tmp/memcached.sock 使用 pymemcache 绑定:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

CACHES = {    'default': {        'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',        'LOCATION': 'unix:/tmp/memcached.sock',    }}

Memcached 有一个很好的特性,就是它可以在多台服务器上共享一个缓存。这意味着你可以在多台机器上运行 Memcached 守护进程,程序将把这组机器作为一个 单一 的缓存,而不需要在每台机器上重复缓存值。要利用这个特性,请在 LOCATION 中包含所有服务器地址,可以是分号或逗号分隔的字符串,也可以是一个列表。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

缓存是通过运行在 IP 地址 172.19.26.240 和 172.19.26.242 上的 Memcached 实例共享的,这两个实例都在 11211 端口上:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

CACHES = {    'default': {        'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',        'LOCATION': [            '172.19.26.240:11211',            '172.19.26.242:11211',        ]    }}

缓存是由运行在 IP 地址 172.19.26.240(端口11211)、172.19.26.242(端口11212)和 172.19.26.244(端口11213)上的 Memcached 实例共享的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

CACHES = {    'default': {        'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',        'LOCATION': [            '172.19.26.240:11211',            '172.19.26.242:11212',            '172.19.26.244:11213',        ]    }}

基于内存的缓存有一个缺点:因为缓存的数据存储在内存中,如果服务器崩溃数据将丢失。内存并不是用来永久存储数据的,所以不要依赖基于内存的缓存作为唯一的数据存储。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

Django 3.2增加了 PyMemcacheCache 后端。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

3.2 版后已移除MemcachedCache`后端已被废弃,因为 python-memcached 有一些问题,而且似乎没有维护。使用 PyMemcacheCache 或 PyLibMCCache 代替。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

数据库缓存

Django 可以在数据库中存储缓存数据。如果你有一个快速、索引正常的数据库服务器,这种缓存效果最好。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

用数据库表作为你的缓存后端:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

  • 将 BACKEND 设置为 django.core.cache.backends.db.DatabaseCache
  • 将 LOCATION 设置为数据库表的 tablename。这个表名可以是没有使用过的任何符合要求的名称。

在这个例子中,缓存表的名称是 my_cache_table文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

CACHES = {    'default': {        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',        'LOCATION': 'my_cache_table',    }}

创建缓存表¶

使用数据库缓存之前,必须通过命令创建缓存表:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

python manage.py createcachetable

该表的格式与 Django 数据库缓存系统期望的一致,表名为LOCATION 。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

如果使用多个数据库缓存,createcachetable 会为每个缓存创建一个表。如果使用多个数据库, createcachetable 观察数据库路由器的 allow_migrate() 方法。像 migrate 一样, createcachetable 不会影响已经存在的表,它只创建缺失的表。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

多数据库

如果在多数据库中使用缓存,需要设置数据库缓存表的路由指令。数据库缓存表在 django_cache 应用程序中显示为 CacheEntry 的模型名。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

比如,下面的路由可以将所有缓存读取操作指向 cache_replica ,并且所有的写操作指向 cache_primary。缓存表将会只同步到 cache_primary文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

class CacheRouter:    """A router to control all database cache operations"""
    def db_for_read(self, model, **hints):        "All cache read operations go to the replica"        if model._meta.app_label == 'django_cache':            return 'cache_replica'        return None
    def db_for_write(self, model, **hints):        "All cache write operations go to primary"        if model._meta.app_label == 'django_cache':            return 'cache_primary'        return None
    def allow_migrate(self, db, app_label, model_name=None, **hints):        "Only install the cache model on primary"        if app_label == 'django_cache':            return db == 'cache_primary'        return None

如果没有指定路由指向数据库缓存模型,缓存后端将使用默认的数据库。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

文件系统缓存

基于文件的后端序列化并保存每个缓存值作为文件。可将 BACKEND 设置为 "django.core.cache.backends.filebased.FileBasedCache" 并将 LOCATION 设置为路径。比如,在 /var/tmp/django_cache 存储缓存数据,使用以下配置:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

CACHES = {    'default': {        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',        'LOCATION': '/var/tmp/django_cache',    }}

如果使用 Windows 系统,将驱动器号放在路径开头,如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

CACHES = {    'default': {        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',        'LOCATION': 'c:/foo/bar',    }}

目录路径是绝对路径。确保配置指向的目录存在并且可由运行 Web 服务器的系统用户读写,或者可以直接由运行 Web 服务器的系统用户创建。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

本地内存缓存

如果配置文件中没有指定其他缓存,这是默认缓存。可将 BACKEND 设置为 "django.core.cache.backends.locmem.LocMemCache"。例如:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

CACHES = {    'default': {        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',        'LOCATION': 'unique-snowflake',    }}

LOCATION 被用于标识各个内存存储。如果只有一个 locmem 缓存,可以忽略 LOCATION 如果有多个本地内存缓存,那么至少要为其中一个起个名字,以便将它们区分开。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

使用自定义缓存后端

使用 Python 导入路径作为 BACKEND 的 CACHES 配置中的 BACKEND,像这样:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

CACHES = {    'default': {        'BACKEND': 'path.to.backend',    }}

缓存参数文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

每个缓存后端可以通过额外的参数来控制缓存行为。这些参数在 CACHES 配置中作为附加键提供。有效参数如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

  • TIMEOUT :缓存的默认超时时间,以秒为单位。这个参数默认为 300 秒(5 分钟)。你可以将 TIMEOUT 设置为 None,这样,默认情况下,缓存键永远不会过期。值为 0 会导致键立即过期(实际上是 “不缓存”)。
  • OPTIONS :任何应该传递给缓存后端的选项。有效的选项列表会随着每个后端而变化,由第三方库支持的缓存后端会直接将其选项传递给底层缓存库。

    实施自有缓存策略的缓存后端(即 locmemfilesystem 和 database 后端)将尊重以下选项:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

    Memcached 后端将 OPTIONS 的内容作为关键字参数传递给客户端构造函数,允许对客户端行为进行更高级的控制。具体用法请看下文。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

    • MAX_ENTRIES :删除旧值之前允许缓存的最大条目。默认是 300 。
    • CULL_FREQUENCY :当达到 MAX_ENTRIES 时,被删除的条目的比例。实际比例是 1 / CULL_FREQUENCY,所以将 CULL_FREQUENCY 设置为 2,即当达到 MAX_ENTRIES 时将删除一半的条目。这个参数应该是一个整数,默认为 3

      CULL_FREQUENCY 的值为 0 意味着当达到 MAX_ENTRIES 时,整个缓存将被转储。在某些后端(特别是 database ),这使得缓存速度  快,但代价是缓存未命中更多。

  • KEY_PREFIX。一个自动包含在 Django 服务器使用的所有缓存键中的字符串(默认为前缀)。

    查看 缓存文档 获取更多信息。

  • VERSION :Django 服务器生成的缓存键的默认版本号。

    查看 缓存文档 获取更多信息。

  • KEY_FUNCTION 一个字符串,包含一个函数的点分隔路径,该函数定义了如何将前缀、版本和键组成一个最终的缓存键。

    查看 缓存文档 获取更多信息。

配置一个文件系统后端,超时为 60 秒,最大容量 1000 项:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

CACHES = {    'default': {        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',        'LOCATION': '/var/tmp/django_cache',        'TIMEOUT': 60,        'OPTIONS': {            'MAX_ENTRIES': 1000        }    }}

站点缓存

一旦缓存设置完毕,使用缓存最简便的方式是缓存整个站点。在 MIDDLEWARE 中添加 'django.middleware.cache.UpdateCacheMiddleware' 和 'django.middleware.cache.FetchFromCacheMiddleware' ,如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

MIDDLEWARE = [    'django.middleware.cache.UpdateCacheMiddleware',    'django.middleware.common.CommonMiddleware',    'django.middleware.cache.FetchFromCacheMiddleware',]

最后,在 Django 设置文件里添加下面的必需配置:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

  • CACHE_MIDDLEWARE_ALIAS -- 用于存储的缓存别名。
  • CACHE_MIDDLEWARE_SECONDS -- 应缓存每个页面的秒数。
  • CACHE_MIDDLEWARE_KEY_PREFIX -- 如果使用相同的 Django installation ,通过多站点进行缓存共享,请将此值设置为站点名,或者设置成在Django 实例中唯一的其他字符串,以此防止键冲突。如果你不介意,可以设置成空字符串。

在请求和响应标头允许的情况下,FetchFromCacheMiddleware 缓存状态为200的 GET 和 HEAD 响应。对于具有不同查询参数的相同URL的请求的响应被认为是单独的页面,并分别缓存。这个中间件期望一个HEAD请求的响应头与相应的GET请求具有相同的响应头;在这种情况下,它可以为HEAD请求返回一个缓存的GET响应。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

view视图缓存

  • django.views.decorators.cache.cache_page()¶

使用缓存框架的通用办法是缓存视图结果。django.views.decorators.cache 定义了一个 cache_page 装饰器,它将自动缓存视图的响应:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

from django.views.decorators.cache import cache_page
@cache_page(60 * 15)def my_view(request):    ...

cache_page 使用了一个单独的参数:缓存过期时间,以秒为单位。在上面的例子里,my_view() 视图的结果将缓存15分钟。(注意,我们用 60 * 15 这样的方式编写,目的是方便阅读。 60 * 15 将计算为 900,也就是15分钟乘以每分钟60秒。)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

cache_page 设置的缓存超时优先于 Cache-Control 头中的 ``max-age'' 指令。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

和缓存站点一样,对视图缓存,以 URL 为键。如果许多 URL 指向相同的视图,每个 URL 将被单独缓存。继续以 my_view 为例,如果你的 URLconf 是这样的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

urlpatterns = [    path('foo/<int:code>/', my_view),]

那么 /foo/1/ 和 /foo/23/ 的请求将被分别缓存,正如你所料。但一旦部分 URL (比如 /foo/23/ )已经被请求,那么随后的请求都将使用缓存。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

cache_page 也可以传递可选关键字参数 cache,它指引装饰器在缓存视图结果时使用特定的缓存(来自 CACHES 设置)。默认情况下,将使用默认缓存,但你可以指定任何你想要的缓存:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

@cache_page(60 * 15, cache="special_cache")def my_view(request):    ...

你可以基于每个视图覆盖缓存前缀。cache_page 传递了一个可选关键字参数 key_prefix ,它的工作方式与中间件的 CACHE_MIDDLEWARE_KEY_PREFIX 相同。可以这样使用它:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

@cache_page(60 * 15, key_prefix="site1")def my_view(request):    ...

key_prefix 和 cache 参数可能需要被一起指定。key_prefix 参数和 CACHES 下指定的 KEY_PREFIX 将被连接起来。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

此外, cache_page 在响应中自动设置 Cache-Control 和 Expires 头, 这会影响 下游缓存.文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

在 URLconf 中指定视图缓存

在 URLconf 中使用 cache_page 时,可以这样包装视图函数。如文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

urlpatterns = [    path('foo/<int:code>/', my_view),]

将 my_view 包含在 cache_page 中:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

from django.views.decorators.cache import cache_page
urlpatterns = [    path('foo/<int:code>/', cache_page(60 * 15)(my_view)),]

模板片段缓存文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

使用 cache 模板标签(tag)来缓存模板片段。要使模板能够访问这个标签,请将 {% load cache %} 放在模板顶部。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

{% cache %} 模板标签在给定的时间里缓存片段内容。它需要至少两个参数:缓存时效时间(以秒为单位),缓存片段的名称。如果缓存失效时间被设置为 None ,那么片段将被永久缓存。名称不能使变量名。例如:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

{% load cache %}{% cache 500 sidebar %}    .. sidebar ..{% endcache %}

缓存失效时间可以是模板变量,只要模板变量解析为一个整数值即可。例如,模板变量 my_timeout 被设置成 600,那么下面两个例子是一样的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

{% cache 600 sidebar %} ... {% endcache %}{% cache my_timeout sidebar %} ... {% endcache %}

避免在模板中重复,可以在某处设置缓存失效时间,然后复用这个值。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

默认情况下,缓存标签会先尝试使用名为 "template_fragments" 的缓存。如果这个缓存不存在,它将回退使用默认缓存。你可以选择一个备用缓存后端与 using 关键字参数一起使用,这个参数必须是标签的最后一个参数。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html

{% cache 300 local-thing ...  using="localcache" %}
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47405.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/bc/47405.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定