饮冰三年-人工智能-Django淘宝拾遗-87-进一步探讨 Django 和 Redis 的缓存机制

发布时间 2023-11-27 10:39:53作者: 逍遥小天狼

上一篇:斑马斑马-05-白云之上-Redis初识

    缓存在 Web 开发中具有极其重要的作用,它可以显著提高应用程序的性能和响应速度,减少服务器负载改善用户体验。

    在 Django 中,声明式缓存和编程式缓存是两种常见的缓存模式。声明式缓存是通过装饰器或设置来标记某些视图函数或数据查询结果需要进行缓存,而编程式缓存则是通过编写代码来手动存储和获取特定的数据或资源。声明式缓存通常用于缓存整个视图函数的输出或页面内容,而编程式缓存则更加灵活,可以针对特定的数据或操作进行定制化的缓存设置和管理。

一、环境准备

1:redis安装

redis安装上篇文章已经介绍,还可以通过docker镜像的快速搭建的方法。

docker run -d -p 6379:6379 --name redis-master redis:latest 

2:创建Django项目

就通过Pycharm创建一个包含App01简单Django项目

3:创建数据库

就是用原有的sqllite数据库,数据表也用框架本身提供的那套,直接执行migrate命令即可

4:使用DRF框架

安装并配置,编写url和view(这里简单记录一下view中的方法)

import time
from django.contrib.auth.models import User
from django.http import HttpRequest, HttpResponse
from rest_framework import viewsets
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import serializers


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'password')
        extra_kwargs = {'password': {'write_only': True}}


class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    time.sleep(2)
    serializer_class = UserSerializer


@api_view(('GET',))
def get_user(request: HttpRequest) -> HttpResponse:
    qs = User.objects.all()
    time.sleep(2)
    return Response({
        "code": 100,
        "data": UserSerializer(qs, many=True).data
    })
View

达到的效果就是使用postman或者DRF的接口调用成功,数据正常返回。

5:setting中配置redis

5.1 安装django-redis

pip install django-redis

5.2 配置setting文件

CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',  # 修改为你的 Redis 服务器地址和端口
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
        }
    }
}
setting配置文件

二、声明式缓存

 Django的声明式缓存是通过使用 cache_page 装饰器来实现的,它可以直接应用于视图函数。这样,整个页面的输出将被缓存,以提高后续请求的性能。

1:给单个函数加缓存

from django.views.decorators.cache import cache_page

@cache_page(timeout=120)
@api_view(('GET',))
def get_user(request: HttpRequest) -> HttpResponse:
    qs = User.objects.all()
    time.sleep(2)
    return Response({
        "code": 100,
        "data": UserSerializer(qs, many=True).data
    })
View Code

你可以用postman请求,通过接口的响应速度(我们接口中睡眠了2秒),来判断是否使用了缓存。

也可以通过观察 Django Debug Toolbar调试工具 上的SQL请求详情去判断

 还可通过redis数据库查询

2:给DRF类中方法加缓存

from django.utils.decorators import method_decorator


@method_decorator(cache_page(60 * 2), name='list')
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
View Code

三、编程式缓存

编程式缓存的优点在于,它允许你在代码的特定部分手动控制缓存,而不是依赖于全局的声明式缓存设置。这使得你可以根据需要在不同的地方使用不同的缓存策略,或者在代码执行过程中动态决定是否进行缓存。

1:给单个函数加缓存(通过django.core.cache

@api_view(('GET',))
def get_user2(request: HttpRequest) -> HttpResponse:
    cache_key = 'my_cache_key:get_user'  # 1:可自定义key值
    qs = cache.get(cache_key)
    if not qs:
        # 2:如果缓存中没有数据,执行取数据逻辑,并将结果放入缓存(粒度控制更自由)
        qs = User.objects.all()
        cache.set(cache_key, qs, timeout=60 * 2)  # 缓存 15 分钟
        time.sleep(2)
    return Response({
        "code": 100,
        "data": UserSerializer(qs, many=True).data
    })
给单个函数加缓存

2:给单个函数加缓存(通过redis_cli

@api_view(('GET',))
def get_user3(request: HttpRequest) -> HttpResponse:
    redis_cli = get_redis_connection()
    cache_key = 'my_cache_key:get_user3'  # 1:可自定义key值
    cached_data = redis_cli.get(cache_key)
    if cached_data:
        json_qs = json.loads(cached_data.decode('utf-8'))
    else:
        # 2:如果缓存中没有数据,执行取数据逻辑,并将结果放入缓存(粒度控制更自由)
        qs = User.objects.all()
        json_qs = UserSerializer(qs, many=True).data
        # 3: 使用 JSON 序列化器将数据序列化后存储到缓存
        redis_cli.set(cache_key, json.dumps(json_qs), ex=60 * 2)  # 缓存 15 分钟
        # 模拟耗时操作
        time.sleep(2)

    return Response({
        "code": 100,
        "data": json_qs
    })
给单个函数加缓存