Django(39)使用redis配置缓存
前言
动态网站的基本权衡是,它们是动态的。每次用户请求页面时,Web服务器都会进行各种计算 - 从数据库查询到模板呈现再到业务逻辑 - 以创建站点访问者看到的页面。从处理开销的角度来看,这比标准的文件读取文件系统服务器要耗时多了。对于大多数Web应用程序来说,这种开销并不是什么大问题。因为大多数Web应用程序只是中小型网站
,没有拥有一流的流量。但对于中到高流量
的站点,尽可能减少开销
是至关重要的,这就是缓存的用武之地。缓存某些内容是为了保存昂贵计算的结果,这样就不必在下次执行计算。
Django
框架带有一个强大的缓存系统,可以保存动态页面,因此不必为每个请求计算它们。Django
提供不同级别的缓存粒度:可以缓存特定视图的输出,也可以只缓存页面中难以生成的部分或者可以缓存整个站点。
Redis
是一个内存数据库(现在已经支持内存数据持久化到硬盘当中,重新启动时,会自动从硬盘进行加载),由于其性能极高,因此经常作为中间件、缓存使用。
django应用redis缓存
django中安装第三方库,使用如下命令
pip3 install django-redis
1.settings配置
首先,我们在settings.py
中配置如下代码
CACHES = {
# default 是缓存名,可以配置多个缓存
"default": {
# 应用 django-redis 库的 RedisCache 缓存类
"BACKEND": "django_redis.cache.RedisCache",
# 配置正确的 ip和port
"LOCATION": "redis://127.0.0.1:6379",
"OPTIONS": {
# redis客户端类
"CLIENT_CLASS": "django_redis.client.DefaultClient",
# redis连接池的关键字参数
"CONNECTION_POOL_KWARGS": {
"max_connections": 100
}
# 如果 redis 设置了密码,那么这里需要设置对应的密码,如果redis没有设置密码,那么这里也不设置
# "PASSWORD": "123456",
}
}
}
2.全站缓存
2.1 全站缓存的2个中间件
- FetchFromCacheMiddleware :从缓存中读取数据
- 缓存状态为200的
GET
和HEAD
请求的响应(除非响应头中设置不进行缓存) - 对具有不同查询参数的相同
URL
的请求的响应被认为是各自不同的页面,并且被分别单独缓存。 - 该中间件会使用与对应的
GET
请求相同的响应头来回答HEAD
请求,即可以为HEAD请求返回缓存的GET响应。
- 缓存状态为200的
- UpdateCacheMiddleware :将数据更新到缓存中
- 该中间件会自动在每个响应中设置几个
headers
:- 设置
Expires
为当前日期/时间 加上 定义的CACHE_MIDDLEWARE_SECONDS
值,GMT时间
- 设置响应的
Cache-Control
的max-age
,值是定义的CACHE_MIDDLEWARE_SECONDS值。
- 设置
- 如果视图设置了自己的缓存时间(即设置了
Cache-Control
的max age
),那么页面将被缓存直到到期时间,而不是CACHE_MIDDLEWARE_SECONDS
。 - 如果
USE_I18N
设置为True
,则生成的缓存key将包含当前语言的名称,这样可以轻松缓存多语言网站,而无需自己创建缓存密钥。 - 如果
USE_L10N
设置为True
并且USE_TZ
被设置为True
,缓存key
也会包括当前语言
- 该中间件会自动在每个响应中设置几个
在settings
的中间件中设置:
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
# 其他中间件...
'django.middleware.cache.FetchFromCacheMiddleware',
]
注意:UpdateCacheMiddleware
必须是第一个中间件,FetchFromCacheMiddleware
必须是最后一个中间件
2.2 全站缓存的必填设置
将以下必须设置添加到Django
的settings
文件中
CACHE_MIDDLEWARE_ALIAS = 'default'
CACHE_MIDDLEWARE_SECONDS = 60*60
CACHE_MIDDLEWARE_KEY_PREFIX = "cache_redis_demo_first"
配置解释如下:
- CACHE_MIDDLEWARE_ALIAS:用于存储的缓存别名
- CACHE_MIDDLEWARE_SECONDS:每个页面应缓存的秒数
- CACHE_MIDDLEWARE_KEY_PREFIX:用于生成缓存
key
的前缀,如果使用相同的Django
安装在多个站点之间共享缓存,请将其设置为站点名称或此Django实例特有的其他字符串,以防止发生密钥冲突。如果你不在乎,请使用空字符串。
2.3 全站缓存示例
接着我们在视图中写入如下函数:
def index(request):
# 通过设置时间戳,进行多次访问,可以看到时间戳的变化,就可以得知是否是缓存页面了
return HttpResponse('当前时间戳:' + str(time.time()))
我们打开浏览器访问127.0.0.1/redis/
,多次访问该url,发现时间戳不会改变,这是因为我们在配置中设置了缓存时间为1个小时。
我们可以打开浏览器的网络请求中查看response header
,查看max_age
和Expires
,如下图
我们会发现响应头中已经有了缓存的时间,说明我们缓存配置成功了
3.视图函数缓存
一般情况下,我们不会使用全局缓存,因为全局缓存,只要服务器返回状态码是200,他都会将其缓存下来,这样会影响性能,所以我们一般都会使用视图缓存,针对某个视图,需要进行缓存,则使用缓存。
3.1通过装饰器cache_page
from django.views.decorators.cache import never_cache, cache_page
@cache_page(20)
def view_cache(request, num):
return HttpResponse(f"num:{num},时间戳:{time.time()}")
- cache_page除了默认的
timeout
参数外,还有两个可选的关键字参数- cache,示例代码:
@cache_page(60 * 15, cache="special_cache")
, 该cache
指向settings
中配置的缓存的名称,默认是"default"
- key_prefix:缓存
key
的前缀,与CACHE_MIDDLEWARE_KEY_PREFIX
功能相同
- cache,示例代码:
- 如果多个
url
指向同一个视图函数,会为每个url建立一个单独的缓存,例如:
urlpatterns = [
path('view_cache/<int:num>/', views.view_cache, name="view_cache")
]
/view_cache/1/
和/view_cache/2/
请求会分别进行缓存
3.2通过urls中配置cache_page
在URLconf
中指定视图缓存,而不是在视图函数上硬编码装饰器,可以进一步解耦缓存和视图函数之间的关系,使用起来更灵活
from django.views.decorators.cache import cache_page
urlpatterns = [
path('view_cache/<int:num>/', cache_page(20)(views.view_cache), name="view_cache")
]
以上2种方式作用是一样的,这里我们更加推荐3.2这种写法
4.低级缓存
有时我们不想缓存整个页面数据,而只是想缓存某些费时查询
并且基本不会改变
的数据,可以通过一个简单的低级缓存API
实现,该API
可以缓存任何可以安全pickle
的Python
对象:字符串,字典,模型对象列表等
django.core.cache.caches
from django.core.cache import caches
cache1 = caches['myalias']
cache2 = caches['myalias']
# 判断为True
if cache1 is cache2:
...
说明:
- 可以通过
CACHES
类似字典一样的方式访问settings
中配置的缓存,在同一个线程中重复请求相同的别名将返回相同的对象 - 如果指定的
myalias
不存在,将引发InvalidCacheBackendError
- 为了线程安全性,为会每个线程返回缓存的不同实例
- 作为快捷方式, 默认缓存(default)可以使用
django.core.cache.cache
:
# 使用 default 缓存
from django.core.cache import cache
# 上面的cache等同于下面的写法
from django.core.cache import caches
cache = caches['default']
django.core.cache.cache
from django.core.cache import cache
# 使用 redis 的一般用法
cache.set('manul_set', 'ok')
manul_set = cache.get('manul_set')
# 可以手动设置 timeout,如果不指定timeout,默认是 300秒,如果指定为None,则代表没有过期时间
cache.set("key", "value", timeout=None)
# 可以获取key的超时设置(ttl:time to live)
# 返回值的3种情况:
# 0: key 不存在 (或已过期)
# None: key 存在但没有设置过期
# ttl: 任何有超时设置的 key 的超时值
cache.set("foo", "value", timeout=25)
cache.ttl("foo") # 得到 25
cache.ttl("not-existent") # 得到 0
# 让一个值永久存在
cache.persist("foo")
cache.ttl("foo") # 得到 None
# 指定一个新的过期时间
cache.set("foo", "bar", timeout=22)
cache.ttl("foo") # 得到 22
cache.expire("foo", timeout=5)
cache.ttl("foo") # 得到 5
# 支持 redis 分布式锁, 使用 上下文管理器 分配锁
with cache.lock("somekey"):
do_some_thing()
# 使用全局通配符的方式来检索或者删除键
cache.keys("foo_*") # 返回所有匹配的值, 如 ["foo_1", "foo_2"]
# 删除 键
cache.delete_pattern("foo_*") # 支持通配符
实战案例
首先创建个common
文件夹,然后在文件夹下面创建cache_helper.py
文件,写入如下代码
from django.core.cache import cache
def get_cache_or_exc_func(key, func, *args, **kwargs):
"""
根据传入的key和func,先获取缓存内容,没有则使用func计算并保存结果
:param key: 缓存的key
:param func: 计算函数
:param args: 可变参数
:param kwargs: 可变字典
:return: 缓存的n内容或func计算的结果
"""
# 加上cache锁
with cache.lock(key+'lock'):
# 获取缓存中的变量
result = cache.get(key)
if result:
# 存在,则直接返回缓存结果
return result
else:
# 不存在,则计算数据,得到结果
result = func(*args, **kwargs)
# 将结果保存到缓存中
cache.set(key, result)
# 返回结果
return result
然后配置url
路径,如下
urlpatterns = [
path('lower_level_cache/', views.lower_level_cache, name="lower_level_cache"),
]
最后在视图中,写入2个函数
def get_result():
"""做一些费时但不经常变更的操作,这里模拟等待3秒"""
time.sleep(3)
return 'ok'
def lower_level_cache(request):
result = get_cache_or_exc_func('test_key', get_result)
return JsonResponse({"result": result})
现在我们打开浏览器,访问127.0.0.1/redis/low_level_cache/
,我们会发现,浏览器不会马上响应,而是等待了3秒,因为我们代码中模拟等待了3秒,而且我们是第一次访问,没有缓存,当第二次访问时,就立马响应了,原因是此时已经有了缓存
5.session缓存
在settings.py
文件中,配置如下代码即可
# 配置session的引擎为cache
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
# 此处别名依赖缓存的设置
SESSION_CACHE_ALIAS = 'default'
Django(39)使用redis配置缓存的更多相关文章
- django 时区设置 redis token缓存策略
from django.utils.timezone import utcimport datetime datetime.datetime.utcnow().replace(tzinfo=utc)# ...
- 从零搭建Spring Boot脚手架(6):整合Redis作为缓存
1. 前言 上一文我们整合了Mybatis Plus,今天我们会把缓存也集成进来.缓存是一个系统应用必备的一种功能,除了在减轻数据库的压力之外.还在存储一些短时效的数据场景中发挥着重大作用,比如存储用 ...
- Django分别使用Memcached和Redis作为缓存的配置(Linux环境)
1 使用memcached 1.1 安装memcached 安装(Linux) sudo apt install memcached 启动 #方式一: service memcached start ...
- Django使用redis实现缓存
实现缓存的方式,有多种:本地内存缓存,数据库缓存,文件系统缓存.这里介绍使用Redis数据库进行缓存. 配置 CACHES = { "default": { "BACKE ...
- spring配置redis注解缓存
前几天在spring整合Redis的时候使用了手动的方式,也就是可以手动的向redis添加缓存与清除缓存,参考:http://www.cnblogs.com/qlqwjy/p/8562703.html ...
- django使用redis做缓存
Django 使用 Redis 做缓存 django中应用redis:pip3 install django-redis - 配置 CACHES = { "default": { ...
- Django之使用redis缓存session,历史浏览记录,首页数据实现性能优化
Redis缓存session 配置Django缓存数据到redis中 # diango的缓存配置 CACHES = { "default": { "BACKEND&quo ...
- Django使用Redis进行缓存详细最全流程
背景和意义服务器数据非经常更新.若每次都从硬盘读取一次,浪费服务器资源.拖慢响应速度.而且数据更新频率较高,服务器负担比较大.若保存到数据库,还需要额外建立一张对应的表存储数据.在Django中建立表 ...
- Djnago中缓存配置(redis配置案例)
Django中提供了6种缓存方式: 开发调试 内存 文件 数据库 Memcache缓存(python-memcached模块) Memcache缓存(pylibmc模块) 配置文件 # 内存 CACH ...
随机推荐
- thinkphp5安装php高版本出现No input file specified.解决
<IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews RewriteEngine On RewriteCond %{RE ...
- Typora+PicGo+cos图床打造开发者文档神器
一.Typora简介 markdown简单.高效的语法,被每一个开发者所喜爱.Typora又是一款简约.强悍的实时渲染markdown编辑器.本文将介绍Typora搭配PicGo与腾讯cos对象存储( ...
- hdu4756 最小树+树形dp
题意: 给你一个完全图,让你在上面找到一颗最小树,然后问破坏这个最小树的某一条边后用其他边连接(要求最小)成新的树,然后输出破坏每一条边后最小树中最大的那个. 思路: 先跑出一 ...
- PAT 乙级 -- 1014 -- 福尔摩斯的约会
题目简介 大侦探福尔摩斯接到一张奇怪的字条:"我们约会吧! 3485djDkxh4hhGE 2984akDfkkkkggEdsb s&hgsfdk d&Hyscvnm&quo ...
- UVA11427玩纸牌(全概率+递推)
题意: 一个人玩纸牌游戏,他每天最多玩n局,枚举获胜的概率是a/b,每天玩牌只要获胜概率达到p,那么他今天就不玩了,明天接着玩,如果有一天他的概率没有达到p,(没有达到p的话他今天一定是玩 ...
- ASLR 的关闭与开启(适用于 Windows7 及更高版本)
ASLR 是一种针对缓冲区溢出的安全保护技术,通过对堆.栈.共享库映射等线性区布局的随机化,通过增加攻击者预测目的地址的难度,防止攻击者直接定位攻击代码位置,达到阻止溢出攻击的目的的一种技术 有的时候 ...
- Windows核心编程 第十一章 线程池的使用
第11章 线程池的使用 第8章讲述了如何使用让线程保持用户方式的机制来实现线程同步的方法.用户方式的同步机制的出色之处在于它的同步速度很快.如果关心线程的运行速度,那么应该了解一下用户方式的同步机制是 ...
- 神经网络与机器学习 笔记—Rosenblatt感知机
Rosenblatt感知机器 感知器在神经网络发展的历史上占据着特殊位置:它是第一个从算法上完整描述的神经网络.它的发明者Rosenblatt是一位心里学家,在20世纪60年代和70年代,感知器的启发 ...
- <JVM上篇:内存与垃圾回收篇>01-JVM与Java体系结构
笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...
- Redis 的持久化
原文链接:https://www.changxuan.top/?p=1386 Redis 是一个非关系型的内存数据库,使用内存存储数据是它能够进行快速存取数据的原因之一. 在实际应用中,常有人提倡把 ...