Code前端首页关于Code前端联系我们

Django 框架意识:配备强大的缓存系统

terry 2年前 (2023-09-24) 阅读数 66 #后端开发

动态网站的基本权衡是它们是动态的。每当用户请求页面时,Web 服务器都会执行各种计算(从数据库查询到模板呈现再到业务逻辑)以创建访问者看到的页面。从处理成本的角度来看,这比从文件系统读取文件的标准服务器布置要昂贵得多。对于中高流量的网站,必须尽可能减少开销。这就是缓存发挥作用的地方。

缓存是为了保存昂贵的计算结果,这样你下次就不用再计算它们了。下面是一些伪代码,解释了如何在动态生成的网页中使用此方法:给出一个 URL,尝试找到此缓存页面如果该页面已缓存:返回缓存页面

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

否则:生成页面缓存生成的页面(下次)返回生成的页面

Django带有一个强大的缓存系统,允许为每个请求计算动态页面。为了方便起见,Django 提供了不同级别的缓存粒度。您可以缓存特定视图、仅缓存难以生成的部分或缓存整个站点。

设置缓存

缓存系统需要进行少量设置。也就是说,您需要告诉它缓存的数据应该放置在哪里 - 是在数据库中、在文件系统中还是直接在内存中。这是一个影响缓存性能的重要决定;是的,某些缓存类型比其他类型更快。

缓存设置点位于配置文件的缓存配置中。这里有缓存配置的所有可用值的描述。

Memcached

Memcached 是一个完全基于内存的缓存服务器。它是 Django 原生支持的最快、最高效的缓存类型。它最初是为了处理 LiveJournal.com 的高负载而开发的,然后由 Danga Interactive 开放。 。 Facebook 和维基百科等网站使用它们来减少数据库访问并显着提高网站性能。

Memcached 作为守护进程运行,并分配指定数量的 RAM。它所做的只是提供一个快速界面来添加、检索和删除缓存中的数据。所有数据都直接存储在内存中,因此没有数据库开销或文件系统使用。

安装 Memcached 本身后,您需要安装 Memcached 绑定。有多种可用的 Python Memcached 绑定; Django 支持的两个是 pylibmc 和 pymemcache。

在 Django 中使用 Memcached:

  • 将 BACKEND 设置为 django.core.cache.backends.memcached.PyMemcache 或Cache django.core.cache.backends.memcached。 PyLibMCCache (取决于您选择的 memcached 绑定)。
  • LOCATION 设置为 ip:port 值,其中 ipipDem 是 M 地址 端口 正在运行 Memcached 端口,或者设置为 unix:path 值,其中 path 是 Memcached Unix 套接字文件的路径。

Memcached运行在localhost(127.0.0.1)端口11211,使用pymemcache绑定:

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

Memcached❀Memcached❀❀x文件可以通过本地me访问mcached.sock

使用 pymemcache绑定:

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

Memcached 有一个很好的功能,它可以在多个服务器上共享缓存。这意味着您可以在多台计算机上运行 Memcached 守护进程,并且该程序会将这组计算机视为单个 缓存,而无需在每台计算机上复制缓存值。要利用此功能,请将所有服务器地址包含在 LOCATION 中,以分号或逗号分隔的字符串或列表的形式。

缓存由在 IP 地址 172.19.26.240 和 172.19.26.242 上运行的 Memcached 实例共享,两者均在端口 11211 上:

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

缓存由 Memcached 2.1.2.1 共享。 Memcached 实例共享的 172.19.26.242(端口 11212)、172.19.26.242(端口 11212)和 172.19.26.244(端口 11213):

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',        ]    }}

基于内存的缓存有一个缺点:因为当服务器崩溃时,缓存的数据存储在内存中。内存并不是为了永久存储数据而设计的,因此不要依赖基于内存的缓存作为唯一的数据存储。

Django 3.2 添加了 PyMemcacheCache 后端。

自版本 3.2 起已删除 MemcachedCache`后端已被删除,因为python-memcached存在一些问题且未维护。请改用 PyMemcacheCachePyLibMCCache

数据库缓存

Django 可以将缓存数据存储在数据库中。如果您有一个快速、索引良好的数据库服务器,这种类型的缓存效果最好。

使用数据库表作为缓存后端:

  • BACKEND设置为django.core.cache.Databas❝LOCATION设置为表名 来自数据库表。该表名可以是任何符合要求的未使用的名称。

本例中缓存表的名称为my_cache_table

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

创建缓存表¶

缓存,在使用数据库之前,必须先创建Use数据库。 表的格式表名称为LOCATION,正如Django数据库缓存系统所期望的那样。

如果您使用多个数据库缓存,createcachetable 为每个缓存创建一个表。使用多个数据库时,createcachetable 观察数据库路由器的allow_migrate() 方法。与 migrate 一样,createcachetable 不会影响现有表,它只会创建丢失的表。

多个数据库

如果在多个数据库中使用缓存,则必须为数据库缓存表设置路由指令。数据库缓存表在 django_cache 应用程序中显示为 CacheEntry 的模型名称。

例如,以下路径可以将所有缓存读取操作定向到cache_replica,将所有写入操作定向到cache_primary。缓存表仅与 cache_primary 同步。

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

如果未指定指向数据库缓存模型的路径,则缓存后端使用默认数据库。

文件系统缓存

基于文件的后端将每个缓存值序列化并将其存储为文件。您可以将 ​​BACKEND

设置为 "django.core.cache.backends.filebased.FileBasedCache" 并将 设置为 "django.core.cache.backends.filebased。基于​​文件的缓存" "将 和 放在 ❀ LOAD 上 例如,要将缓存数据存储在 /var/tmp/django_cache,请使用以下配置:

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

如果您有 Windows -system,将盘符放在路径的开头,如下:

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

目录路径为绝对路径。确保配置指向的目录存在,并且可以被运行Web服务器的系统用户读写,或者可以由运行Web服务器的系统用户直接创建。

本地内存缓存

如果配置文件中未指定其他缓存,则这是默认缓存。您可以将 ​​BACKEND 设置为 "django.core.cache.backends.locmem.LocMemCache"。例如:

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

LOCATION用于标识每个内存存储。如果只有一个 locmem 缓存,可以忽略 LOCATION 如果有多个本地内存缓存,请至少为其中一个命名以区分它们。

使用自定义缓存后端

CACHES♿❓配置中使用Python导入路径作为BACKEND。 ,如下所示:

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

缓存参数

每个缓存后端都可以通过附加参数控制缓存行为。这些参数作为 CACHES 配置中的附加键提供。有效参数如下:

  • TIMEOUT:默认缓存超时时间,单位为秒。此参数默认为 300 秒(5 分钟)。您可以将 ​​TIMEOUT
设置为 None,以便缓存密钥默认永不过期。值 0 将使密钥立即过期(实际上“不缓存”)。

  • OPTIONS:传递到缓存后端的所有选项。有效选项列表随每个后端而变化,第三方库支持的缓存后端将其选项直接传递到底层缓存库。

    实施自己的缓存策略的缓存后端(即locmem文件系统和s)遵循以下选项:

    Memcached 客户端传递Content后OPTIONS 作为客户端构造函数的关键字参数,允许对客户端行为进行更高级的控制。请参见具体用途如下。

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

      CULL_FREQUENCY0,这意味着当达到 MAX_ENTRIES 时,将转储整个缓存。在某些后端(尤其是数据库),这使得缓存更快,但代价是更多缓存未命中。

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

    请参阅缓存文档以获取更多信息。

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

    请参阅缓存文档以获取更多信息。

  • KEY_FUNCTION 一个字符串,带有点分隔的函数路径,该函数定义如何将前缀、版本和密钥组合成最终的缓存密钥。

    请参阅缓存文档以获取更多信息。

  • 配置文件系统后端,超时为 60 秒,最大容量为 1000 个项目:

    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''djan.chrom'le'djan。 ,如下:

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

    最后,在 Django 设置文件中添加以下所需配置:

    • CACHE_MIDDLEWARE_ALIAS -- 用于存储的缓存别名。
    • CACHE_MIDDLEWARE_SECONDS - 每个页面应缓存的秒数。
    • CACHE_MIDDLEWARE_KEY_PREFIX -- 如果您使用相同的 Django 安装来跨多个站点共享缓存,请设置将此值设置为站点名称,或将其设置为 Django 实例中唯一的另一个字符串以避免键冲突。 。如果你不在乎,可以将其设置为空字符串。

    FetchFromCacheMiddleware 如果请求和响应标头允许,缓存状态为 200 的 GET 和 HEAD 响应。对具有不同请求参数的同一 URL 的请求的响应被视为单独的页面并单独缓存。该中间件期望 HEAD 请求与相应的 GET 请求具有相同的响应标头;在这种情况下,它可能会返回 HEAD 请求的缓存 GET 响应。

    view 视图缓存

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

    使用缓存视图结果的常见方法是缓存视图结果。django.views.decorators.cache定义了cache_page装饰器,它将自动缓存视图的响应:❀_page:缓存使用参数时间,以秒为单位。在上面的示例中,my_view() 视图的结果缓存了 15 分钟。 (请注意,为了便于阅读,我们将其写为 60 * 15。由

    cache_page 设置的缓存超时优先于 Cache 中的“Max-Age”指令-Control header.

    与缓存站点一样,视图也会被缓存,以 URL 为键。如果多个 URL 指向同一个视图,则每个 URL 会单独缓存。继续 将 my_view

    视为举个例子,如果你的 URLconf 是这样的:

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

    那么 /foo/1///3 是请求被单独缓存,正如你所期望的那样,但是。如果 URL 的一部分 (例如 /foo/23/) 被请求,后续请求将使用缓存。 获取用于特定缓存的装饰(从 Caches 设置)默认情况下使用默认缓存,但您可以指定所需的任何缓存:

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

    您可以基于每个视图设置缓存 -Override 前缀。 cache_page 传递可选关键字参数 key_prefix,其工作方式与中间件CACHE_KEY_MIDDLEWARE_IX。 您可以像这样使用它:

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

    key_prefix cache参数可能需要一起指定。参数key_prefixCACHES 下指定的KEY_PREFIX 已连接。

    此外,cache_page 自动降低在响应 ching 中过期的 缓存控制 响应。

    指定 URLconf 缓存中的视图

    如果您在 URLconf 中使用 cache_page,您可以像这样包装视图函数。例如,

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

    包含my_viewcache_page:❙模板❙❙❙❙cache cache使用

    模板标签(tag)用来缓存模板片段。要使模板可以访问此标签,请将 {% load cache %} 放在模板顶部。

    {% cache %} 模板标签会缓存片段内容一段时间。它至少需要两个参数:缓存老化时间(以秒为单位)和缓存片段的名称。如果缓存过期时间设置为None,则片段将永久存储在缓存中。该名称不能是变量名。例如:

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

    缓存过期时间可以是模板变量,只要模板变量解析为整数值即可。例如,如果模板变量 my_timeout 设置为 600,则以下两个示例是相同的:

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

    为了避免模板中的重复,您可以在某处设置缓存过期时间重用这个值。

    默认情况下,缓存标签首先尝试使用名为“template_fragments”的缓存。如果该缓存不存在,则会回退到默认缓存。您可以选择与 using 关键字参数一起使用的备用缓存后端,该参数必须是标记的最后一个参数。

    {% cache 300 local-thing ...  using="localcache" %}

    版权声明

    本文仅代表作者观点,不代表Code前端网立场。
    本文系作者Code前端网发表,如需转载,请注明页面地址。

    发表评论:

    ◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

    热门