缓存主要用来加速慢存储的访问效率,减少对数据库的操作,提升页面访问速度。
一、CentOS 安装 Redis
yum install epel-releas # 添加 EPEL 仓库
yum update # 更新 yum 源
yum -y install redis
systemctl start redis # 启动 redis 服务
配置可远程连接 Redis
修改配置文件:/etc/redis.conf
:
# 找到 `bind 127.0.0.1`,注释掉这一行
# 将 protected-mode 修改为 no
protected-mode no
# 保存重启 `redis` 服务
systemctl restart redis
二、Django 中缓存设置
Django 支持的缓存机制
Django
中可以配置多种缓存源,支持的缓存设置有:
- 内存缓存
- 文件缓存
- 数据库缓存
-
memcached
缓存 -
redis
缓存
内存缓存
local-memory-caching
,线程安全的,进程间独立,即每个进程一份缓存,Django
默认配置,配置示例如下:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
}
}
文件缓存
filesystem caching
,将数据缓存到文件系统中,配置示例如下:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebackend.FileBaseCache',
'LOCATION': '/var/tmp/django_cache',
}
}
数据库缓存
database caching
,需要创建缓存用的表,意义不大,不推荐使用,配置示例如下:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DataaseCache',
'LOCATION': 'my_cache_table',
}
}
memcached
Django
推荐的缓存系统,也是分布式的(分布式逻辑在客户端),Django
内置支持,集成度比较好,配置示例如下:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242.11211',
],
}
}
redis 缓存
使用 redis
缓存有两种思路:
-
Django
模块:django-redis
或django-redis-cache
- 直接使用
Redis
包操作Redis
,不使用Django
模块,缺点是无法使用内置缓存模块的接口,不推荐
配置 redis 缓存
安装
pip install django-redis==4.9.0
pip install hiredis
默认安装的 redis
是最新版,使用缓存时可能会报错:redis.exceptions.DataError: Invalid input of type: 'CacheKey'.
,可将版本降为 2.10.6
:
pip install redis==2.10.6
hiredis
的作用是提升 redis
解析性能,具体测试结果可在 https://github.com/redis/hiredis-py#benchmarks
配置
配置 Projects/settings.py
:
# Redis 缓存
REDIS_URL = 'redis://192.168.131.131:6379/1'
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': REDIS_URL,
'TIMEOUT': 300,
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'PASSWORD_CLASS': 'redis.connection.HiredisParser',
},
'CONNECTION_POOL_CLASS': 'redis.connection.BlockingConnectionPool',
}
}
应用场景和缓存粒度
使用缓存首先要知道在哪缓存、缓存什么,即使用场景,千万不要以为缓存一定能优化访问效率,一定要先知道项目的业务特点。
Django
提供的各种粒度的缓存方案:
- 整站缓存:配置中间件即可,不推荐
- 整个页面缓存
- 局部数据缓存
整站缓存
配置 settings
中间件:
MIDDLEWARE = [
# 站点缓存 , 注意必须在第一个位置
'django.middleware.cache.UpdateCacheMiddleware',
...
# 站点缓存, 注意必须在最后一个位置
'django.middleware.cache.FetchFromCacheMiddleware',
]
若内容在缓存中存在,则使用 FetchFromCacheMiddleware
获取内容并返回,在返回之前,判断缓存中是否已存在,若不存在则 UpdateCacheMiddleware
会将缓存保存至缓存,从而实现全站缓存。
单页面缓存
from django.shortcuts import render, HttpResponse
import time
from django.views.decorators.cache import cache_page
@cache_page(60 * 15)
def index(request):
ctime = str(time.time())
return render('index.html', locals())
局部数据缓存
class BookListView(View):
"""书籍列表"""
def get(self, request):
res = {"code": 0, "msg": "查询成功", "data": []}
book_list = cache.get('book_list')
if not book_list:
book_list = models.Book.objects.all()
cache.set('book_list', book_list, 10 * 60)
res["data"] = json.loads(serializers.serialize("json", book_list))
return JsonResponse(res)
首先从缓存中获取数据,若不存在则从数据库取出,并放入缓存中,以便下次使用。
URLconf 中使用缓存
场景:多个 URL
指向同一视图函数,但只想缓存一部分 URL
:
from django.views.decorators.cache import cache _page
urlpatterns = [
url(r'^foo/([0-9]{1,2})/$',cache_page(60 * 15)(index)),
url(r'^$', cache_page(60 * 30)(IndexView.as_view()), name='order'),
]
URL
缓存缓存的也是整个页面,需要考虑是否整个页面都应该缓存。
模板页面(局部页面)缓存
模板中使用缓存时比较推荐的一种方式,可以充分利用缓存粒度,可保证只缓存那些适合缓存的 HTML
片段:
{% load cache %}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Myblog</title>
</head>
<body>
<h2>测试redis</h2>
<div><p>非缓存地段</p></div>
{% cache 10 aabbcc %}
<div><p>这里缓存</p></div>
{% endcache %}
</body>
测试缓存
在配置好后,应用之前可以先用 Django shell
测试是否能够成功:
python manage.py shell
from django.core.cache import cache
cache.set('book_list', '流畅的 Python', 60 * 60)
cache.has_key('book_list')
cache.get('book_list)
缓存使用原则
- 静态页面
- 不经常变动的页面或数据,实时性不高的数据,如文章热门排行榜等
- 不建议缓存整个页面,因为页面会经常变动,但是可以缓存侧边栏,侧边栏不经常变动
- 复杂逻辑生成的
HTML
片段,使用缓存可以减少多次重复操作
参考文章
- linux下redis的安装与django-redis使用方法
- django_redis 中文网