django:缓存

一,缓存

动态网站最基本的权衡就是,它们是动态的。每次用户请求页面时,Web服务器都会进行各种计算——从数据库查询到模板呈现再到业务逻辑——以创建站点访问者所看到的页面。从处理开销的角度来看,这比标准的“读取文件离开文件系统”服务器安排要昂贵得多。
对于大多数Web应用程序来说,这种开销并不是什么大问题。大多数网络应用程序不是washingtonpost.com或slashdot.org;它们只是一些流量一般的中小型网站。但对于中高流量的网站来说,尽可能减少开销是必要的。
这就是缓存的用武之地。
缓存是为了保存昂贵计算的结果,以便下次不必执行计算。

下面是一些伪代码,解释了缓存如何为动态生成的Web页面工作:

given a URL, try finding that page in the cache
if the page is in the cache:
    return the cached page
else:
    generate the page
    save the generated page in the cache (for next time)
    return the generated page

Django提供了一个健壮的缓存系统,可以保存动态页面,这样就不必为每个请求计算页面。为了方便起见,Django提供了不同级别的缓存粒度:可以缓存特定视图的输出,可以只缓存难以生成的部分,也可以缓存整个站点。Django还可以很好地与“下游”缓存一起工作,比如Squid和基于浏览器的缓存。这些是你不能直接控制的缓存类型,但是你可以提供提示(通过HTTP头)关于你的站点的哪些部分应该缓存,以及如何缓存。
缓存系统需要进行少量的设置。也就是说,您必须告诉它缓存的数据应该位于何处——是在数据库中,还是在文件系统中,还是直接在内存中。这是一个影响缓存性能的重要决定;是的,有些缓存类型比其他类型更快。你的缓存首选项在你的设置文件的缓存设置中。

二,缓存类型及配置

django提供了几种不同的缓存方式,下面是对所有缓存可用值的解释。

1,Memcached

Memcached是Django本地支持的速度最快、效率最高的缓存类型,它完全是一个基于内存的缓存服务器,最初是为处理LiveJournal.com的高负载而开发的,后来由Danga Interactive开源。Facebook和Wikipedia等网站使用它来减少数据库访问并显著提高网站性能。
Memcached作为守护进程运行,并分配了指定数量的RAM。它所做的只是提供一个快速接口,用于在缓存中添加、检索和删除数据。所有数据都直接存储在内存中,因此不存在数据库或数据库的开销。

Memcached是一个高性能分布式内存对象缓存系统,通过在内存中缓存数据与对象减少读取数据库的次数,从而提高动态网站响应速度,实现动态网站减轻数据库系统负载。
适用于超大型网站。

  • Set BACKEND to django.core.cache.backends.memcached.MemcachedCache or django.core.cache.backends.memcached.PyLibMCCache
  • Set LOCATION to ip:port
使用时需要安装Memcached服务器,并通过python-memcached 与 pylibmc进行调用,
CACHES = {
    
    
    # 默认缓存数据表
    'default': {
    
    
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',	#必须项 或使用django.core.cache.backends.memcached.PyLibMCCache
        'LOCATION': '127.0.0.1:11211', #必须项  或使用'unix:/tmp/memcached.sock' 使用PyLibMCCache时不需要unix:前缀。
    }
}

Memcached的一个优秀特性是它能够在多个服务器上共享缓存。这意味着您可以在多台机器上运行Memcached守护进程,并且程序将把这组机器视为单个缓存,而不需要在每台机器上重复缓存值。要利用此特性,请在位置上包括所有服务器地址。

以分号或逗号分隔的字符串或列表的形式:

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

关于Memcached的最后一点是基于内存的缓存有一个缺点:由于缓存的数据存储在内存中,因此如果服务器崩溃,数据将丢失。
显然,内存不是用于永久数据存储的,因此不要依赖基于内存的缓存作为唯一的数据存储。

毫无疑问,任何Django缓存后端都不应该用于永久存储,它们都旨在作为缓存而非存储的解决方案。

2,数据库缓存

Django可以将其缓存的数据存储在您的数据库中。 如果您拥有快速索引良好的数据库服务器,则此方法效果最佳。

适合中大型网站。

  • Set BACKEND to django.core.cache.backends.db.DatabaseCache
  • Set LOCATION to tablename
CACHES = {
    
    
    'default': {
    
    
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',	#必须项
        'LOCATION': 'my_cache_table',	#必须项 该名称可以是您想要的任何名称,只要它是数据库中尚未使用的有效表名即可。
    }
}

1,创建缓存表
在使用数据库缓存之前,必须使用此命令创建缓存表:python manage.py createcachetable
这将在数据库中创建一个表,该表的格式符合Django的数据库缓存系统的要求。表的名称取自LOCATION

2,使用多个数据库
如果使用多个数据库缓存,则createcachetable会为每个缓存创建一个表。像数据迁移一样,createcachetable不会触及现有表。 它只会创建丢失的表。
如果使用多个数据库,则createcachetable据数据库路由器的allow_migrate()方法进行路由。为了进行路由,数据库高速缓存表在名为django_cache的应用程序中显示为名为CacheEntry的模型。 该模型不会出现在模型缓存中,但是可以将模型详细信息用于路由目的。
如果要打印将要运行的SQL,而不是运行它,请使用createcachetable --dry-run选项。

以下路由器会将所有缓存读取操作定向到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

3,文件系统缓存

基于文件的后端序列化并将每个缓存值存储为单独的文件。

适合中小型网站。

  • set BACKEND to django.core.cache.backends.filebased.FileBasedCache
  • set LOCATION to a suitable directory
CACHES = {
    
    
    'default': {
    
    
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', #必须项
        'LOCATION': '/var/tmp/django_cache', #必须项 必须保证服务器对列出的路径具有读写权限。
    }
}

如果使用的是Windows,需要引用完整路径:

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

4,本地内存缓存

django默认的缓存方式。在无条件使用memcached,需要内存缓存的情况下使用local-memory缓存,此内存是多线程,线程安全。

只适用于开发与测试。

  • set BACKEND to django.core.cache.backends.locmem.LocMemCache
  • set LOCATION to a suitable directory
CACHES = {
    
    
    'default': {
    
    
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', #必须项
        'LOCATION': 'unique-snowflake', #非必须项 用于标识各个内存存储区。如果只有一个locmem缓存,可以省略该位置;但是,如果您有一个以上的本地内存缓存,则需要为其中至少一个指定名称,以便将它们分开。
    }
}

使用本地内存缓存有一个明显缺点:每个进程都有自己的私有缓存实例,这意味着不可能进行跨进程缓存。这显然还意味着本地内存缓存的内存效率不是特别高,因此它可能不是生产环境的好选择。这有利于发展。

5,虚拟缓存

Django带有一个“虚拟”缓存,该缓存实际上并没有缓存-它只是实现了缓存接口,而不做任何事情。

如果生产站点在各个地方都使用了重型缓存,但是在开发/测试环境中却不想缓存并且不想将代码更改为后者的特殊情况,这将非常有用。

  • set BACKEND to django.core.cache.backends.dummy.DummyCache
CACHES = {
    
    
    'default': {
    
    
        'BACKEND': 'django.core.cache.backends.dummy.DummyCache', #必须项
    }
}

6,使用自定义的缓存后台

尽管Django开箱即用地支持许多缓存后端,但有时可能希望使用自定义的缓存后端:要将外部缓存后端与Django一起使用。

适合需要使用外部的缓存系统的情况。

  • set BACKEND to path.to.backend
如使用redis缓存:
1.安装依赖 pip install django-redis
2.在stting中配置CACHES,可以设置多个缓存,根据名字使用
        CACHES = {
    
    
            "default": {
    
    
                "BACKEND": "django_redis.cache.RedisCache",
                "LOCATION": "redis://127.0.0.1:6379", #如果redis server设置了密码,需要使用‘密码@redis://127.0.0.1:6379’
                "OPTIONS": {
    
    
                    "CLIENT_CLASS": "django_redis.client.DefaultClient", 
                    "CONNECTION_POOL_KWARGS": {
    
    "max_connections": 100}
                }
            }
        },
        #另添加缓存
        "JERD": {
    
     }
3.根据名字去连接池中获取连接
        from django_redis import get_redis_connection
        conn = get_redis_connection("default")

缓存还有多个可选参数:见官方文档Cache arguments部分

三,缓存使用示例

1,缓存类型选择与配置

示例使用数据库缓存:

CACHES = {
    
    
    # 默认缓存数据表
    'default': {
    
    
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'my_cache_table',
        'TIMEOUT': 60,        # TIMEOUT设置缓存的生命周期,以秒为单位,若为None,则永不过期
        'OPTIONS': {
    
    
            'MAX_ENTRIES': 1000,            # MAX_ENTRIES代表最大缓存记录的数量
            'CULL_FREQUENCY': 3,            # 当缓存到达最大数量之后,设置剔除缓存的数量
        }
    },
    # 设置多个缓存数据表
    'MyDjango': {
    
    
        'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
        'LOCATION': 'MyDjango_cache_table',
    }
}

还要创建缓存数据表:

python manage.py createcachetable

在这里插入图片描述

2,选择缓存的使用方式

1,全站缓存The per-site cache

一旦设置好了缓存,使用缓存的最简单方法就是缓存整个站点。

添’django.middleware.cache.UpdateCacheMiddleware‘与’django.middleware.cache.FetchFromCacheMiddleware’ 到MIDDLEWARE设置中。

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

然后,将以下必需设置添加到Django配置文件中:

CACHE_MIDDLEWARE_ALIAS = "default" 用于存储的缓存路径.
CACHE_MIDDLEWARE_SECONDS = 15 每个页面的缓存秒数.
CACHE_MIDDLEWARE_KEY_PREFIX = "MyDjango" 指定唯一站点名称,在基于分布式部署的访问流量分配基础上,区分服务器的缓存数据。

视图与模板:

index/views.py:
def index(request):
    return render(request, 'index.html')


templates/index.html:
<html>
<body>
    <div>
        <div>Hello Django</div>
    </div>
</body>
</html>

访问任意页面都会在my_cache_table中生成相应缓存:
在这里插入图片描述

虽然易于使用,但存在缺点:如果网站规模比较大,则相应的缓存数据会多很多,就会对缓存系统施加很大压力。不推荐使用。

2,视图缓存The per-view cache

使用缓存框架的更精细的方法是缓存单个视图的输出。
当用户发出请求时,如果请求的视图函数已产生缓存,则以缓存数据作为响应,从而减少请求处理的资源与时间消耗。
django.views.decorators.cache定义了一个cache_page装饰器,它将自动缓存视图的响应。 易于使用。

视图与模板:

from django.shortcuts import render
from django.views.decorators.cache import cache_page
# 参数cache与配置属性CACHE_MIDDLEWARE_ALIAS相同
# 参数key_prefix与配置属性CACHE_MIDDLEWARE_KEY_PREFIX相同
# 参数timeout与配置属性CACHE_MIDDLEWARE_SECONDS相同
# CACHE_MIDDLEWARE_SECONDS的优先级高于参数timeout
@cache_page(timeout=10, cache='MyDjango', key_prefix='MyView')
def index(request):
    return render(request, 'index.html')


templates/index.html:
<html>
<body>
    <div>
        <div>Hello Django</div>
    </div>
</body>
</html>

访问指定页面都会在MyDjango中生成相应缓存:
在这里插入图片描述

3,路由缓存Specifying per-view cache in the URLconf

是一种特殊的视图缓存,但与视图缓存在工作过程上有所不同。

路由与模板:

from django.urls import path
from . import views
from django.views.decorators.cache import cache_page

urlpatterns = [
    # 网站首页设置路由缓存
    path('1', cache_page(timeout=10, cache='MyDjango', key_prefix='MyURL')(views.index), name='index'),
    path('2', views.index, name='index'),
]


templates/index.html:
<html>
<body>
    <div>
        <div>Hello Django</div>
    </div>
</body>
</html>
  • 当两个路由指向同一视图函数时,路由缓存会在访问视图函数之前判断该路由是否已产生缓存进而判断是否要访问。
    在这里插入图片描述

4,模板缓存Template fragment caching

对模板中的一部分数据设置缓存,如对header设置缓存。

视图与模板:

def index(request):
    return render(request, 'index.html')


<html>
<body>
    <div>
    {
    
    # 设置模版缓存 #}
    {
    
    % load cache %}
{
    
    #     10代表生命周期 #}
{
    
    #     MyTemp代表缓存数据的cache_key字段 #}
{
    
    #     using="MyDjango"代表缓存数据表 #}
    {
    
    % cache 10 MyTemp using="MyDjango" %}
        <div>Hello Django</div>
{
    
    #     缓存结束 #}
    {
    
    % endcache %}
    </div>
</body>
</html>

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/dangfulin/article/details/108598734