【19.0】路飞项目之Redis的使用

【一】Django中使用Redis

【1】自定义的通用方案(跟框架无关)

(1)引入(无池)

  • 自定义计数器
import redis


class TextResponse(APIView):
    def get(self, request):

        conn = redis.Redis(host='127.0.0.1', port=6379, db=0, decode_responses=True)
        # 每访问一次,Redis中的 num 值 都会 +1
        # 该方案没有池,只能一个接一个处理请求
        conn.incrby('num', 1)
        result = conn.get('num')
        print(result)
        return CommonResponse(msg='Redis测试成功')
  • 每访问一次该路由,在Redis中都会将 num 进行自加一操作

(2)迭代(有池)

  • luffyCity\luffyCity\utils\common_redis_pool.py
import redis

# 创建redis连接池
POOL = redis.ConnectionPool(max_connections=30, host="127.0.0.1", port=6379, decode_responses=True)

import redis


class TextResponse(APIView):
    def get(self, request):
        # 从连接池中获取连接对象
        conn = redis.Redis(connection_pool=POOL)
        # 每访问一次,Redis中的 num 值 都会 +1
        conn.incrby('num', 1)
        result = conn.get('num')
        print(result)
        return CommonResponse(msg='Redis测试成功')

【2】借助Django中的第三方模块

  • django中有个模块,django-redis,方便我们快速集成redis

(1)下载安装

pip install django-redis

(2)配置文件中添加配置

  • luffyCity\luffyCity\settings\dev.py
###############Redis配置文件#################
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379",  # 走 Redis 协议
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {"max_connections": 100}  # 连接池大小
            # "PASSWORD": "123", # 有密码可以自配置密码
        }
    }
}

(3)视图类中使用

# 导入模块
from django_redis import get_redis_connection


# 视图类中使用
conn = get_redis_connection()  # 从连接池中拿出一个链接
  • 示例
# 导入模块
from django_redis import get_redis_connection

class TextResponse(APIView):
    def get(self, request):
        
        conn = get_redis_connection()  # 从连接池中拿出一个链接
        conn.incrby('num')
        result = conn.get('num')
        print(result)
        conn.set('name', f'dream&{result}')

        return CommonResponse(msg='Redis测试成功')

【二】Django之缓存

【1】内置缓存

  • django 是大而全的框架,内置了很多web开发需要的东西,缓存内置了
from django.core.cache import cache
cache.set('key','value',5) # 存放值
res=cache.get('key') # 取值

【2】更多方案

  • 缓存:可以把django中的一个变量(数据),存放到某个位置,下次还可以取出来
  • 之前用过:默认放在:内存中,其实可以放在文件中,数据库,redis。。。。

【3】放在redis

  • 通过配置,控制存放在哪,只要如下写,就会放在redis中
###############Redis配置文件#################
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379",  # 走 Redis 协议
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {"max_connections": 100}  # 连接池大小
            # "PASSWORD": "123", # 有密码可以自配置密码
        }
    }
}

【4】示例

  • Redis 不支持放列表 ,需要转成字符串才能存进去 ---- 可以采用 JSON序列化一下
  • django缓存最强大之处在于,只要是python的变量,任意类型都可以,尽管使用set设置值
    • 缓存中可以设置任意类型的值,比如字典,列表,字符串,数字,元组,集合,对象等
# 测试缓存
class TextResponse(APIView):
    def get(self, request):
        # 将缓存放到cache中 (键,值,失效时间)
        cache.set('name', 'dream', 30)

        # conn = get_redis_connection()  # 从连接池中拿出一个链接
        # conn.lpush("l2",[1, 3, 4, 5, 6]) # Redis 不支持放列表 ,需要转成字符串才能存进去 ---- 可以采用 JSON序列化一下

        # django缓存最强大之处在于,只要是python的变量,任意类型都可以,尽管使用set设置值
        # 缓存中可以设置任意类型的值,比如字典,列表,字符串,数字,元组,集合,对象等
        l = [1, 'hope', [1, 3, 4, 5, 6], '蚩梦']
        cache.set('ll1', l)
        result = cache.get('name')
        print(result)
        return CommonResponse(msg='Redis测试成功')

【三】celery介绍

  • 异步任务开启线程,不好管理)

  • 定时任务

  • 延迟任务

  • 借助于第三方框架,celery:芹菜,吉祥物,可以实现上面的三个功能

  • 分布式的异步任务框架 celery

【简解】

  • Celery是一个分布式的异步任务框架,可以实现异步任务、定时任务和延迟任务的功能。
    • 在Django中使用Celery,可以更好地处理异步任务,并提高应用的性能和可扩展性。

(1)安装Celery和Redis

  • 首先,在Django项目中安装Celery和Redis:
pip install celery redis

(2)配置Celery

  • 在Django项目的settings.py文件中,添加Celery的配置信息:
# settings.py

CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
  • 上述配置中
    • CELERY_BROKER_URL指定了Celery的消息代理(这里使用Redis)
    • CELERY_RESULT_BACKEND指定了Celery任务结果的存储位置。

(3)创建celery.py文件

  • 在Django项目的根目录下创建一个名为celery.py的文件,并添加以下内容:
# celery.py

import os
from celery import Celery

# 设置Django环境变量
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project.settings')

# 创建Celery实例
app = Celery('your_project')

# 加载Celery配置
app.config_from_object('django.conf:settings', namespace='CELERY')

# 自动发现异步任务
app.autodiscover_tasks()

(4)定义异步任务

  • 在Django项目的某个应用中,创建tasks.py文件,并定义异步任务:
# your_app/tasks.py

from celery import shared_task

@shared_task
def send_email_task(to, subject, message):
    # 模拟发送邮件的耗时操作
    print(f"Sending email to {to}: {subject}")
    print(f"Message: {message}")
  • 在上面的代码中,使用shared_task装饰器定义一个名为send_email_task的异步任务。

(5)调用异步任务

  • 在Django的视图函数或其他逻辑中,可以通过调用异步任务来实现对应的功能:
# views.py

from your_app.tasks import send_email_task

def some_view(request):
    # 异步调用发送邮件任务
    send_email_task.delay("example@example.com", "Hello", "This is a test email")
    return HttpResponse("Task started")
  • 在上述代码中,通过send_email_task.delay()方法异步调用发送邮件任务,并立即返回响应给用户,不会阻塞主线程。

(6)注意事项:

  • 为了确保Celery能够自动发现异步任务,需要在Django项目根目录下运行Celery的worker进程:
    celery -A your_project worker --loglevel=info
    
  • 如果需要使用定时任务和延迟任务,在Celery配置中添加相应的定时器和调度器,例如使用beat_schedule配置项。

(7)总结:

  • 在Django中使用Celery可以实现异步任务、定时任务和延迟任务的功能,提高应用的性能和可扩展性。
  • 需要安装Celery和消息代理(如Redis)。
  • 配置Celery信息在Django的settings.py文件中。
  • 创建celery.py文件来加载Celery配置并自动发现异步任务。
  • 定义异步任务并使用shared_task装饰器进行注册。
  • 在适当的地方调用异步任务并使用.delay()方法来异步执行任务。

【补充】JSON序列化和pickle序列化

  • json序列化 ---> 得到字符串
    • json不能序列化对象(自定义的类的对象)
    • 数据结构:数据的组织形式跟下面不一样
      • 能序列化: 数字,字符串,布尔,列表,字典 时间对象
  • pickle序列化
    • python独有的,二进制形式
    • python可以序列化所有对象 ---> 二进制形式
    • 二进制 ---> 返序列化回来 ---> 对象:属性,有方法
  • json序列化是将数据结构转换为字符串的过程。
    • 它可以将数字、字符串、布尔值、列表、字典和时间对象等基本数据类型进行序列化,从而得到一个字符串表示。
  • 然而,json无法直接将自定义的类对象进行序列化。
    • 只有实现了序列化接口的对象才能被json序列化。
    • 这意味着,如果要对自定义类对象进行序列化,需要先将其转换为可序列化的数据结构,如字典或元组。
    • 一种常见的做法是通过定义类的__dict__属性来将类对象转换为字典,然后再进行json序列化。
  • 下面是一个使用json序列化的示例代码:
import json

data = {
    "name": "John",
    "age": 30,
    "is_employed": True,
    "hobbies": ["reading", "playing guitar"],
    "address": {
        "street": "123 Main St",
        "city": "New York"
    }
}

# 将数据结构序列化为字符串
json_str = json.dumps(data)
print(json_str)
  • 在上述代码中,我们定义了一个data字典,其中包含了不同类型的数据,包括字符串、整数、布尔值、列表以及嵌套字典。

    • 调用json.dumps()函数将data序列化为字符串并打印输出。
  • 相比之下,pickle序列化是Python特有的一种序列化方式,它将对象序列化为二进制数据。

    • 与json不同,pickle可以序列化Python中的任意对象,包括自定义的类对象,并且可以保留对象的属性和方法。
  • 下面是一个使用pickle序列化的示例代码:

import pickle

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def say_hello(self):
        print(f"Hello, my name is {self.name}.")

person = Person("John", 30)

# 对象序列化为二进制数据
pickled_data = pickle.dumps(person)
print(pickled_data)

# 将二进制数据反序列化为对象
unpickled_person = pickle.loads(pickled_data)
unpickled_person.say_hello()
  • 在上述代码中,我们定义了一个Person类,并创建了一个person对象。
    • 调用pickle.dumps()函数将person对象序列化为二进制数据并打印输出。
    • 然后,使用pickle.loads()函数将二进制数据反序列化为对象,并调用对象的方法。

总结:

  • json序列化是将数据结构转换为字符串的过程,可以序列化数字、字符串、布尔值、列表、字典和时间对象;
  • pickle序列化是将对象序列化为二进制数据的过程,可以序列化Python中的任意对象,包括自定义的类对象,并保留对象的属性和方法。

【补充】缓存问题

posted @ 2023-08-19 17:12  Chimengmeng  阅读(19)  评论(0编辑  收藏  举报
/* */