Django 缓存 Cache
Posted 亦非我所愿丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django 缓存 Cache相关的知识,希望对你有一定的参考价值。
文章目录
一、缓存
缓存(Cache)对于创建一个高性能的网站和提升用户体验来说是非常重要的,缓存是一类可以更快的读取数据的介质统称,也指其它可以加快数据读取的存储方式。一般用来存储临时数据,常用介质的是读取速度很快的内存。一般来说从数据库多次把所需要的数据提取出来,要比从内存或者硬盘等一次读出来付出的成本大很多。对于中大型网站而言,使用缓存减少对数据库的访问次数是提升网站性能的关键之一
某些数据访问很频繁的场景下,通过缓存的方式,可以减少对于数据库的连接、查询请求、带宽等多个方面;同时也要注意的是缓存的占用空间,缓存的失效时间
二、Django 缓存应用场景
在Django中,当用户发送一个请求后,通过路由到达视图函数views,当视图函数需要通过template做数据渲染,那么就会通过ORM进行数据库查询操作来获取数据,然后再把数据返回给客户端,也就是页面。
如果每个用户每次请求都需要完整的走一遍数据渲染的过程,将会极大的降低性能,不仅仅数据库压力大,并且客户端也无法及时得到响应内容。
那么这个时候,缓存的使用场景就出现了,在Django中使用场景后,会是这样
当用户发送一个请求后,如果有缓存数据,则直接将缓存数据返回给用户,如果没有,才会查询数据库,并且将查询到的数据写入到缓存,然后将请求返回给客户端,并且客户端下次请求的时候会先访问缓存我数据
三、Django 缓存的五种配置
0、通用配置(以redis为例)
CACHES =
"default":
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://10.55.75.20:6379/0",
'TIMEOUT': 1800, # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
"OPTIONS":
"MAX_ENTRIES": 300, # 最大缓存个数(默认300)
"CULL_FREQUENCY": 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
"CLIENT_CLASS": "django_redis.client.DefaultClient", # redis客户端
"CONNECTION_POOL_KWARGS": "max_connections": 1, # redis最大连接池配置
"PASSWORD": "password", # redis密码
,
'KEY_PREFIX': 'Cache', # 缓存key的前缀(默认空)
'VERSION': 2, # 缓存key的版本(默认1)
,
1、开发调试
CACHES =
'default1':
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
,
2、将缓存信息保存至文件
CACHES =
'default2':
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': os.path.join(BASE_DIR, 'cache'),
,
3、将缓存信息保存至内存
CACHES =
'default3':
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
,
4、将缓存信息保存至数据库
(注:需执行创建表命令 python3 manage.py createcachetable))
CACHES =
'default4':
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table', # 数据库表
,
5、将缓存信息保存至memcache(python-memcached模块)
CACHES =
'default5':
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
,
'default6':
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': 'unix:/tmp/memcached.sock',
,
'default7':
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11211',
]
,
# 我们也可以给缓存机器加权重,权重高的承担更多的请求,如下
'default8':
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': [
('172.19.26.240:11211',5),
('172.19.26.242:11211',10),
]
,
6、将缓存信息保存至memcache(pylibmc模块)
CACHES =
'default9':
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '127.0.0.1:11211',
,
'default10':
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '/tmp/memcached.sock',
,
'default11':
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11211',
]
,
'default12':
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': [
('172.19.26.240:11211',10),
('172.19.26.242:11211',10),
]
,
7、将缓存信息保存至redis(django-redis模块)
CACHES =
"default":
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://10.55.75.20:6379/0",
"OPTIONS":
"MAX_ENTRIES": 300,
"CULL_FREQUENCY": 3,
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": "max_connections": 1,
"PASSWORD": "password",
,
,
四、Django 缓存的三种应用
1、 全站使用
全站使用需要以下两个中间件
中间件最上层:django.middleware.cache.UpdateMiddleware
中间件最下层:django.middleware.cache.FetchFormCacheMiddleware
使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存
在Django官方中指出:“更新”中间件必须是列表中的第一个,“获取”中间件必须是最后一个。细节有点模糊,但如果你想要完整的故事,请参阅下面的MIDDLEWARE。
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
]
middleware关于缓存的全局变量
配置文件位于当前项目中的路径:venv/lib/python3.7/site-packages/django/conf/global_settings.py,建议通过settings.py 定义进行覆盖
CACHE_MIDDLEWARE_KEY_PREFIX = 'champzee' # 表示全局缓存的prefix
CACHE_MIDDLEWARE_SECONDS = 600 # 表示全局缓存的过期时间
CACHE_MIDDLEWARE_ALIAS = 'default' # 表示全局缓存使用的CACHES配置
CACHES配置
配置文件位于当前项目中的路径:venv/lib/python3.7/site-packages/django/conf/global_settings.py,建议通过settings.py 定义进行覆盖
CACHES =
"default":
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://10.55.75.20:6379/0",
'TIMEOUT': 1800,
"OPTIONS":
"MAX_ENTRIES": 300,
"CULL_FREQUENCY": 3,
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": "max_connections": 100,
"PASSWORD": "password",
,
'KEY_PREFIX': 'Cache',
'VERSION': 2,
,
视图函数
def cache1(request):
import time
ctime = time.strftime("%Y-%m-%d %H:%M:%S")
return render(request, 'cache1.html', 'ctime': ctime)
def cache2(request):
import time
ctime = time.strftime("%Y-%m-%d %H:%M:%S")
return render(request, 'cache2.html', 'ctime': ctime)
template模版(cache1和cache2模版)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
ctime <br />
ctime <br />
ctime
</body>
</html>
当我配置好了全局缓存中间件,CACHES redis配置,视图函数,模板之后;下面我发起一个请求,我们通过请求来查看redis是否生成缓存,并且查看缓存有效期是否为600秒
curl http://127.0.0.1:8000/wanglei/cache1
curl http://127.0.0.1:8000/wanglei/cache2
可以看到如下内容,接着我们查看redis
2、视图使用
在视图使用中,我们就不需要配置middleware了,并且关于应用场景优先级第五小节会提到
CACHES配置
CACHES =
"default":
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://10.55.75.20:6379/0",
'TIMEOUT': 1800,
"OPTIONS":
"MAX_ENTRIES": 300,
"CULL_FREQUENCY": 3,
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": "max_connections": 100,
"PASSWORD": "password",
,
'KEY_PREFIX': 'Cache',
'VERSION': 2,
,
视图函数
在视图函数中,cache_page需要引入,并且支持的三个参数为:缓存的失效时间,使用的CACHES的配置,key的前缀
from django.views.decorators.cache import cache_page
@cache_page(timeout=120, cache='default', key_prefix='page3')
def cache3(request):
import time
ctime = time.strftime("%Y-%m-%d %H:%M:%S")
return render(request, 'cache3.html', 'ctime': ctime)
@cache_page(timeout=240, cache='default', key_prefix='page4')
def cache4(request):
import time
ctime = time.strftime("%Y-%m-%d %H:%M:%S")
return render(request, 'cache4.html', 'ctime': ctime)
template模版(cache3和cache4)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
ctime <br />
ctime <br />
ctime
</body>
</html>
当我配置好了 CACHES redis配置,视图函数,模板之后;下面我发起一个请求,我们通过请求来查看redis是否生成缓存,并且查看缓存有效期是否为120和240秒(这里说明一下,我把全局步骤中的部分session缓存进行了清理,所以生成的只有我们局部视图中的缓存)
curl http://127.0.0.1:8000/wanglei/cache3
curl http://127.0.0.1:8000/wanglei/cache4
3、局部使用
只配置template即可(cache),需要先load cache
% load cache %
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
% cache 600 ctime_key1 %
ctime <br />
% endcache %
% cache 300 ctime_ket2 %
ctime <br />
% endcache %
ctime <br />
</body>
</html>
下面我将访问局部cache
curl http://127.0.0.1:8000/wanglei/cache
我们可以看到,间隔一秒的访问,第一次三个ctime都是一样的;而当我第二次访问的时候,前两个数据使用局部缓存,而第三个数据获取到的是当前的时间
在redis中,我们可以看到用户访问生成了两条缓存,第一条key_prefix为ctime_key1,并且ttl时间为600;第二条key_prefix为ctime_key2,并且ttl时间为300秒
五、Django 缓存结论
1、关于优先级
全站配置 > 视图配置 > 局部配置
2、关于缓存名称的生成规则
缓存文件的名称生成方法位于当前项目下源码配置 venv/lib/python3.7/site-packages/django/core/cache/backends/base.py 中,里面定义了default_key_func方法;其实我们定义的全局变量就是传给它,然后它会生成一个统一的cache名称,存入CACHE配置中的缓存地址中
def default_key_func(key, key_prefix, version):
"""
Default function to generate keys.
Construct the key used by all other methods. By default, prepend
the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
function with custom key making behavior.
"""
print('%s:%s:%s' % (key_prefix, version, key))
#return '%s:%s' % (key_prefix, version)
return '%s:%s:%s' % (key_prefix, version, key)
3、关于django 缓存官方文档
https://docs.djangoproject.com/en/2.1/topics/cache/
以上是关于Django 缓存 Cache的主要内容,如果未能解决你的问题,请参考以下文章
Cache._cache.flush_all () 不工作,如何使用 django 和 memcached 清除缓存?
django-redis-cache 和 django-redis 用于使用 Django 进行 redis 缓存的区别?