缓存(Cache)对于创建一个高性能的网站和提升用户体验来说是非常重要的,今天我们就来看看缓存Cache应用场景及工作原理吧,并详细介绍如何在Django中设置Cache并使用它们。
- 提高服务器查询性能,因为放在缓存服务器中的数据一般都是存储在内存当中的,内存中的数据读写效率更高
- 减少服务器端的压力,提高服务器的查询性能
- 减少数据库频繁查询的压力,提升mysql的使用率
一、cache介绍
由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存。
缓存工作原理:缓存是将一些常用的数据保存内存或者memcache中,在一定的时间内有用户来访问这些数据时,则不再去执行数据库及渲染等操作,而是直接从内存或memcache的缓存中去取得数据,然后返回给用户。
Django提供了6种缓存方式:
- 开发调试缓存
- 内存缓存
- 文件缓存
- 数据库缓存
- Memcache缓存(使用python-memcached模块)
- Memcache缓存(使用pylibmc模块)
这里不多介绍,有兴趣的可以去看看官方文档:https://docs.djangoproject.com/en/dev/topics/cache/
二、Redis缓存
Redis可以干什么?
记录评论数、热度、浏览量等。(使用hash)
记录我的收藏、我的文章等列表类型的数据。(使用zset)
记录某篇文章的点赞人员列表。(使用zset)
缓存频繁访问但又不太多的东西,例如:热门推荐。(使用hash)
记录与当前浏览的对象相关的对象,例如:与当前文章相关的文章。(使用list)
记录分类排行榜。(使用zset)
缓存历史记录,如:登录历史等。(使用zset或hash)
Redis的数据结构
不管什么数据类型,在Redis总是以key,value的形式存在,可以通过key获得value的值,redis数据结构类型的差异取决于value的类型。
例如:string类型的value是string,set类型的value是set,zset的value的类型是zset,而key都是string。
=========================================================================================
string(字符串) {"key1":"hello Wrold" }
set(集合) {"key2":{'a':null,'b':null}} set相当于字典,只是所有键对应的值都是null
zset(有序集合) 有顺序的set
hash(字典) {"key3":{'url1':'http://22'}} 可以用来存储用户信息
list(列表) {"key4": [1,2,4,3]
=========================================================================================
string的应用
常见的用途:缓存用户基本信息。
将用户的基本信息序列化成JSON字符串,然后将序列化后的字符串保存到 Redis 来缓存。反过来,当取用户
信息时,会经过一次反序列化。
list的应用
通常用作异步队列、存储列表数据。
hash的应用
无序字典,字典的值只能是字符串。
hash的最后一个元素删除后,该数据结构自动被删除。
hash也可以存储用户的信息,和string不同的是,hash可以对用户信息的每个字段单独存储。
set集合的应用
set的最后一个元素删除后,该数据结构自动被删除。
set中不存在重复元素,利用这个特性,我们可以用来存储防止重复事件发生的情况。例如:在抽奖活动系统中存储中奖用户,防止重复中奖。
Django-Redis
安装 pip install django-redis
Django 支持 Redis cache/session 后端的全功能组件。
说明
Django-Redis可以和Django配合使用,充当cache/session
Django-Redis依赖于pyredis
功能
作为session后端
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"
作为cache后端
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}三、应用
全站使用缓存
使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用 FetchFromCacheMiddleware 获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware 会将缓存保存至缓存,从而实现全站缓存。
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware', # 放在第一
# 其他中间件...
'django.middleware.cache.FetchFromCacheMiddleware', # 放在最后
]
CACHE_MIDDLEWARE_ALIAS = "" # 用于存储的缓存别名
CACHE_MIDDLEWARE_SECONDS = 600 # 每个页面应缓存的秒数
CACHE_MIDDLEWARE_KEY_PREFIX = "" # 如果使用相同的Django安装在多个站点之间共享缓存,请将其设置为站点名称或此Django实例特有的其他字符串,以防止发生密钥冲突。如果你不在乎,请使用空字符串。Django代码中如何使用Cache
当你做好Cache的设置后,在代码中你可以有三种方式使用Cache。
- 在视图View中使用
- 在路由URLConf中使用
- 在模板中使用
单独视图缓存(记得取消全站缓存中间件配置)
当用户首次访问博客首页时,我们从数据库中提取文章列表,并将其存储到缓存里(常用的是内存,这取决于你的设置)。当用户在单位时间内再次访问首页时, Django先检查缓存是否过期(本例是15分钟), 再检查缓存里文章列表资源是否存在,如果存在,直接从缓存中读取数据, 并渲染模板。
from django.shortcuts import render
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # 秒数,这里指缓存 15 分钟
def index(request):
article_list = Article.objects.all()
return render(request, 'index.html', {'article_list': article_list})模板局部缓存:
# 1.引入TemplateTag
{% load cache %}
# 2.使用缓存
{% cache 600 name %} # 第一个参数表示缓存时间,第二个参数是key值(取缓存的时候,需要根据key值取)
缓存内容
{% endcache %}在路由URLConf中使用cache:
前一节中的范例将视图硬编码为使用缓存,因为 cache_page 在适当的位置对 my_view 函数进行了转换。 该方法将视图与缓存系统进行了耦合,从几个方面来说并不理想。 例如,你可能想在某个无缓存的站点中重用该视图函数,或者你可能想将该视图发布给那些不想通过缓存使用它们的人。 解决这些问题的方法是在 URLconf 中指定视图缓存,而不是紧挨着这些视图函数本身来指定。
完成这项工作非常简单: 在 URLconf 中用到这些视图函数的时候简单地包裹一个 cache_page 。以下是刚才用到过的 URLconf : 这是之前的URLconf:
urlpatterns = ('',
(r'^foo/(\d{1,2})/$', my_view),
)以下是同一个 URLconf ,不过用 cache_page 包裹了 my_view :
from django.views.decorators.cache import cache_page
urlpatterns = ('',
(r'^foo/(\d{1,2})/$', cache_page(my_view, 60 * 15)),
)如果采取这种方法, 不要忘记在 URLconf 中导入 cache_page。
视图中连接(手动操作redis):
from django.shortcuts import HttpResponse
from django_redis import get_redis_connection
def index(request):
r = get_redis_connection("default")
r.hmset("name_a", {"key_a": "value_a", "key_b": "value_b"})
return HttpResponse("设置redis")




Comments | NOTHING