Django配合Redis实现数据缓存

django-redis缓存

背景

  • 解决问题:

    • django默认将缓存存放在django-session数据表中,但是这样每次进行用户状态查询的时候都会导致数据库的反复查询,效率不好,因此决定采用redis作为缓存服务器
    • 用户的浏览记录很多时候也需要保存下来,但是我们不能放在数据库中,最好是缓存在redis中
  • 使用模块

    django-redis

  • 参考文档:

    https://django-redis-chs.readthedocs.io/zh_CN/latest/

使用

  1. 安装包

    1
    pip install django-redis
  2. 修改项目中的settings.py配置文件,添加如下配置项

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 本质就是告诉django,将session的缓存服务器切换到redis
    # 配置Redis作为缓存服务器
    CACHES = {
    "default": {
    "BACKEND": "django_redis.cache.RedisCache",
    # location标识redis数据库的地址,格式:redis://IP:PORT/数据库ID
    "LOCATION": "redis://192.168.85.129:6379/3",
    "OPTIONS": {
    "CLIENT_CLASS": "django_redis.client.DefaultClient",
    }
    }
    }

    # 配置redis作为session缓存服务器
    SESSION_ENGINE = "django.contrib.sessions.backends.cache"
    SESSION_CACHE_ALIAS = "default"
  3. 经过上述配置以后,用户产生的session信息就会保存在redis服务器了,此时如果需要缓存用户浏览记录相关的,则需要在对应的视图中进行设置

    1
    2
    3
    4
    5
    6
    7
    # 当我们需要缓存用户的浏览记录的时候,则需要使用原生的redis链接方式连接redis数据库进行操作
    # 此处链接redis,采用django-redis提供的方式,因为已经在settings.py中定义了链接方式,便于统一管理
    from django_redis import get_redis_connection

    # 获取用户的历史浏览记录,使用redis。此处default对应于settings.py配置中CACHES的default
    con = get_redis_connection('default')
    result = con.lrange(user_key, 0, 4)

拓展

  • django中的session中间件

    1
    2
    3
    4
    MIDDLEWARE = [
    # 此物是django的session中间件,如果不允许启动session,则将其注释掉即可
    'django.contrib.sessions.middleware.SessionMiddleware',
    ]
  • 配置redis作为缓存服务器时,SESSION_ENGINE配置的可选值

    1
    2
    3
    4
    5
    6
    7
    8
    # 存储在数据库中,如下设置可以写,也可以不写,这是默认存储方式。
    SESSION_ENGINE='django.contrib.sessions.backends.db'

    # 存储在缓存中:存储在本机内存中,如果丢失则不能找回,比数据库的方式读写更快。
    SESSION_ENGINE='django.contrib.sessions.backends.cache'

    # 混合存储:优先从本机内存中存取,如果没有则从数据库中存取。
    SESSION_ENGINE='django.contrib.sessions.backends.cached_db'

    如果配置缓存存在数据库中,则还需要添加注册的app

    1
    2
    3
    INSTALLED_APPS = [
    'django.contrib.sessions',
    ]

Redis缓存首页的数据库信息

背景

  • 解决问题

    正如生成静态页面的信息一样,首页的数据并不是市场的变化,如果不生成静态文件,那么实际上我们可以通过缓存首页的请求数据,将这些原本存储在mysql中的数据全部换存在redis数据库中,等到需要的时候就直接调用,这样可以减缓mysql数据库重复查询的压力

  • 模块

    1. django-redis
    2. redis数据库
  • 参考文档

    django支持多种缓存逻辑,关于这块可以瞄瞄

    https://django-redis-chs.readthedocs.io/zh_CN/latest/#

使用

  1. 修改项目settings.py文件中的配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 配置Redis作为缓存服务器
    CACHES = {
    "default": {
    "BACKEND": "django_redis.cache.RedisCache",
    "LOCATION": "redis://test.wozaidunkeng.xyz:6379/3",
    "OPTIONS": {
    "CLIENT_CLASS": "django_redis.client.DefaultClient",
    }
    }
    }
  2. 在对应的视图中使用cache缓存数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    from django.shortcuts import render
    from django.views import View
    from django.core.cache import cache
    from django_redis import get_redis_connection
    from goods.models import GoodsType, IndexTypeGoodsType, IndexPromotionBanner, IndexGoodsBanner

    # Create your views here.
    class IndexView(View):
    '''首页信息'''
    def get(self, request):
    # 先尝试获取redis数据库中的数据,如果redis数据库中没有缓存数据,则返回None
    # 存入redis缓存中的数据是什么类型,取出来的数据就是什么类型
    context = cache.get('index_page_data')
    if context:
    print('缓存了首页的数据')
    # 获取所有的商品模型
    goods_type = GoodsType.objects.all()

    # 获取首页banner图
    index_banner = IndexGoodsBanner.objects.all().order_by('index')

    # 获取首页活动
    index_activity = IndexPromotionBanner.objects.all().order_by('index')

    # 获取首页的分类展示内容
    for type in goods_type:
    # 获取type种类首页分类商品的图片信息
    subtitle = IndexTypeGoodsType.objects.filter(type=type, display=1).order_by('index')
    # 获取type种类首页分类商品的文字展示信息
    image = IndexTypeGoodsType.objects.filter(type=type, display=0).order_by('index')

    type.image_banners = image
    type.subtitle = subtitle

    context = {
    "types": goods_type,
    "index_banner": index_banner,
    "index_activity": index_activity,
    }

    # 将首页的数据缓存到redis数据库中
    # 第一个参数是jian,第二个是键对应的值
    # 第三个是过期时间,单位是秒,不设置则表示永远不过期
    cache.set('index_page_data',context,3600)
    else:
    context = dict()

    # 获取用户已保存的购物车的商品数量
    user = request.user
    cart_count = 0
    if user.is_authenticated:
    conn = get_redis_connection('default')
    cart_key = 'cart_{0}'.format(user.id)
    cart_count = conn.hlen(cart_key)
    # 字典中有一个方法:update,如果字典中已经存在某个键,则更新其值,如果没有则添加一个键值对
    context.update(cart_count=cart_count)

    return render(request, 'Good/index.html', context)

拓展

  • cache还可以删除redis数据库中的对应键值

    1
    2
    3
    from django.core.cache import cache

    cache.delete('key名称')
  • 页面优化缓存的顺序(个人理解),但针对不同的情况下需要搭配着使用

    redis数据库 > 静态文件 > mysql数据库