django: cache

One, cache

The most basic trade-off of dynamic websites is that they are dynamic. Every time a user requests a page, the Web server performs various calculations—from database query to template rendering to business logic—to create the page that the site visitor sees. From a processing overhead point of view, this is much more expensive than the standard "read files off the file system" server arrangement.
For most web applications, this overhead is not a big issue. Most web applications are not washingtonpost.com or slashdot.org; they are just small and medium-sized websites with moderate traffic. But for websites with medium to high traffic, it is necessary to reduce overhead as much as possible.
This is where the cache comes in.
Caching is to save the results of expensive calculations so that the calculations do not have to be executed next time.

Here is some pseudo-code that explains how caching works for dynamically generated web pages:

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 provides a robust caching system that can save dynamic pages so that you don't have to count pages for each request. For convenience, Django provides different levels of caching granularity: you can cache the output of a specific view, you can cache only the hard-to-generate parts, or you can cache the entire site. Django also works well with "downstream" caches, such as Squid and browser-based caches. These are the types of caching that you cannot directly control, but you can provide hints (via HTTP headers) about which parts of your site should be cached and how.
The cache system requires a few settings. In other words, you must tell it where the cached data should be located—whether it is in the database, in the file system, or directly in memory. This is an important decision that affects cache performance; yes, some cache types are faster than others. Your cache preferences are in the cache settings of your settings file.

Two, cache type and configuration

Django provides several different caching methods, the following is an explanation of all the available values ​​of the cache.

1,Memcached

Memcached is the fastest and most efficient cache type supported locally by Django. It is entirely a memory-based cache server. It was originally developed to handle the high load of LiveJournal.com and later open sourced by Danga Interactive. Websites such as Facebook and Wikipedia use it to reduce database access and significantly improve website performance.
Memcached runs as a daemon and allocates a specified amount of RAM. All it does is provide a quick interface for adding, retrieving and deleting data in the cache. All data is stored directly in memory, so there is no database or database overhead.

Memcached is a high-performance distributed memory object caching system. It reduces the number of times to read the database by caching data and objects in memory, thereby improving the response speed of dynamic websites and reducing the load of the database system.
Suitable for very large websites.

  • 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:前缀。
    }
}

One of Memcached 优秀特性is its ability to share caches on multiple servers. This means that you can run the Memcached daemon on multiple machines, and the program will treat this group of machines as a single cache instead of repeating the cache value on each machine. To take advantage of this feature, include all server addresses in the location.

As a semicolon or comma separated string or list:

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

The last point about Memcached is that there is a memory-based cache 缺点: because the cached data is stored in memory, if the server crashes, the data will be lost.
Obviously, memory is not used for permanent data storage, so don't rely on memory-based cache as the only data storage.

There is no doubt that any Django cache backend should not be used for permanent storage, they are all intended as a solution for caching rather than storage.

2. Database cache

Django can store its cached data in your database. This method works best if you have a database server with fast indexing.

Suitable for medium and large websites.

  • 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. Create a cache table
Before using the database cache, you must use this command to create a cache table: python manage.py createcachetable
this will create a table in the database whose format meets the requirements of Django's database cache system. The name of the table is taken from LOCATION.

2, the use of multiple databases
If you use more than one database cache, you createcachetablecan create a table for each cache. Like data migration, createcachetableexisting tables are not touched. It will only create missing tables.
If multiple databases are createcachetableused, routing is performed according to the allow_migrate() method of the database router. For routing purposes, the database cache table django_cacheis displayed as CacheEntrya model named in the named application . The model will not appear in the model cache, but the model details can be used for routing purposes.
If you want to print the SQL that will be run instead of running it, use createcachetable --dry-runoptions.

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

The file-based backend serializes and stores each cached value as a separate file.

Suitable for small and medium-sized websites.

  • 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', #必须项 必须保证服务器对列出的路径具有读写权限。
    }
}

If you are using Windows, you need to quote the full path:

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

4. Local memory cache

Django default caching method. Use memcached unconditionally and use local-memory cache when memory cache is required. This memory is multi-threaded and thread-safe.

Only suitable for development and testing.

  • 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缓存,可以省略该位置;但是,如果您有一个以上的本地内存缓存,则需要为其中至少一个指定名称,以便将它们分开。
    }
}

The use of local memory cache has one obvious 缺点: each process has its own private cache instance, which means that cross-process caching is impossible. This obviously also means that the memory efficiency of the local memory cache is not particularly high, so it may not be a good choice for a production environment. This is good for development.

5. Virtual cache

Django comes with a "virtual" cache, which is not actually cached-it just implements the cache interface and doesn't do anything.

This is very useful if the production site uses heavy caching in various places, but does not want to cache and do not want to change the code to the latter special case in the development/test environment.

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

6. Use a custom cache backend

Although Django supports many cache backends out of the box, you may sometimes want to use a custom cache backend: you want to use an external cache backend with Django.

Suitable for situations where an external cache system is required.

  • 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")

There are several optional parameters for the cache: see the official document Cache arguments section .

Three, cache usage example

1. Cache type selection and configuration

Example using database cache:

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

Also create a cache data table:

python manage.py createcachetable

Insert picture description here

2. Choose how to use the cache

1. The per-site cache

Once the cache is set up, the easiest way to use it is to cache the entire site.

Add ' django.middleware.cache.UpdateCacheMiddleware'and' django.middleware.cache.FetchFromCacheMiddleware' to the MIDDLEWAREsettings.

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

Then, add the following required settings to the Django configuration file:

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

Views and templates:

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


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

Visiting any page will generate the corresponding cache in my_cache_table:
Insert picture description here

Although it is easy to use, it does exist 缺点: if the site is relatively large, there will be a lot more cached data, which will put a lot of pressure on the cache system. Not recommended.

2. The per-view cache

A more refined way to use the caching framework is to cache the output of a single view.
When the user makes a request, if the requested view function has been cached, the cached data is used as a response, thereby reducing the resource and time consumption of request processing.
django.views.decorators.cache defines a cache_page decorator, which will automatically cache the response of the view. Easy to use.

Views and templates:

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>

Visiting the specified page will generate the corresponding cache in MyDjango:
Insert picture description here

3. Specifying per-view cache in the URLconf

It is a special view cache, but its working process is different from that of view cache.

Routing and templates:

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>
  • When two routes point to the same view function, the route cache will determine whether the route has been cached before accessing the view function and then determine whether to access it.
    Insert picture description here

4. Template fragment caching

Set the cache for part of the data in the template, such as set the cache for the header.

Views and templates:

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>

Insert picture description here

Guess you like

Origin blog.csdn.net/dangfulin/article/details/108598734