django-redis_redis缓存使用场景

django-redis_redis缓存使用场景前言动态网站的基本权衡是,它们是动态的。每次用户请求页面时,Web服务器都会进行各种计算-从数据库查询到模板呈现再到业务逻辑-以创建站点访问者看到的页面。从处理开销的角度来看,这比标准的文件

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

前言

  动态网站的基本权衡是,它们是动态的。每次用户请求页面时,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的GETHEAD请求的响应(除非响应头中设置不进行缓存)
    • 对具有不同查询参数的相同URL的请求的响应被认为是各自不同的页面,并且被分别单独缓存。
    • 该中间件会使用与对应的GET请求相同的响应头来回答HEAD请求,即可以为HEAD请求返回缓存的GET响应。
  • UpdateCacheMiddleware :将数据更新到缓存中
    • 该中间件会自动在每个响应中设置几个headers
      • 设置Expires为当前日期/时间 加上 定义的CACHE_MIDDLEWARE_SECONDS值,GMT时间
      • 设置响应的Cache-Controlmax-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 全站缓存的必填设置

将以下必须设置添加到Djangosettings文件中

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_ageExpires,如下图
django-redis_redis缓存使用场景
我们会发现响应头中已经有了缓存的时间,说明我们缓存配置成功了
 

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功能相同
  • 如果多个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可以缓存任何可以安全picklePython对象:字符串,字典,模型对象列表等
 

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' 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/165439.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • java指令重排_jvm指令重排

    java指令重排_jvm指令重排引言:在Java中看似顺序的代码在JVM中,可能会出现编译器或者CPU对这些操作指令进行了重新排序;在特定情况下,指令重排将会给我们的程序带来不确定的结果…..1.什么是指令重排?在计算机执行指令的顺序在经过程序编译器编译之后形成的指令序列,一般而言,这个指令序列是会输出确定的结果;以确保每一次的执行都有确定的结果。但是,一般情况下,CPU和编译器为了提升程序执行的效率,会按照一定的规则允…

    2022年10月18日
  • icem网格划分如何给内部面网格,ICEM CFD处理混合网格划分中低质量的问题

    icem网格划分如何给内部面网格,ICEM CFD处理混合网格划分中低质量的问题所谓的混合网格,指的是模型中同时存在结构网格与非结构网格的情况。采用混合网格的主要优势在于:对于复杂的几何,我们可以将其分解成多个几何,对于适合划分结构网格的采用结构网格划分方式,而对于非常复杂的部分,可以使用非结构方式进行划分。然而采用混合网格也有一些缺点:交接面位置网格质量会非常差。因此我们需要采用一些方式对网格质量进行改善。另外对于交界面的处理也存在一些问题。我们先说说在ICEMCFD中进…

  • ubuntu更改密码命令_ubuntu初始密码

    ubuntu更改密码命令_ubuntu初始密码进入Ubuntu,打开一个终端,输入sudosu转为root用户。注意,必须先转为root用户!!! sudopasswduser(user是对应的用户名)。 输入新密码,确认密码。 修改密码成功,挂起,enter进入系统登录界面,输入新密码进入Ubuntu。 …

  • JS 暂时性死区

    JS 暂时性死区JS暂时性死区ES6暂时性死区引用ES6暂时性死区只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。vartmp=123;if(true){tmp=’abc’;//ReferenceErrorlettmp;}上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后…

  • scrapy爬虫学习系列一:scrapy爬虫环境的准备

    scrapy爬虫学习系列一:scrapy爬虫环境的准备系列文章列表:scrapy爬虫学习系列一:scrapy爬虫环境的准备:http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_007_scr

  • 【Linux】Linux中常用操作命令

    【Linux】Linux中常用操作命令

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号