zoukankan      html  css  js  c++  java
  • DAY 83 redis01

    1 redis的连接池
    -在创建连接池的时候,就要指定连接地址
       -以后每次使用都是从连接池中拿一个连接
    2 编码问题,实例化得到redis连接对象(Redis类),可以指定编码
    3 http,应用层协议,基于tcp封装
    -ssh,http,ftp,websocket,DNS---》应用层协议
    -tcp/ip:socket,抽象层
       -UDP:DNS
       
    4 mysql ,redis:cs架构的软件
    -客户端和服务端通信----》通过网络----》基于tcp自封装协议
       -客户端和服务端通信,必须遵循这个协议
       -es,docker:http协议,符合resful规范

    5 手机号登录接口
    6 手机号注册功能
    -前端把手机号,密码,验证码传入---》创建用户
    7 前端的手机号登录,发送验证码,手机号注册

    8 redis:非关系型数据库,缓存数据库,c,性能很高,5大数据类型
    -cs架构的,
       -启动服务端 redis-server 配置文件
       -客户端连接 redis-cli -h  -p
       -windows的RedisDesktopManager客户端连接
    9 python连接redis:普通连接,连接池
    10 redis的字符串操作


    11 python代码 是解释型语言,必须运行在解释器之上
    pyinstaller---可以把这个py文件打包成exe
       打成的exe特别大,不需要解释器了
       -go 编译型,写的代码---》编译成exe
       -java:是编译型---》字节码文件
      -jdk:java开发工具包,包含了jre,jvm
           -jre:java运行环境
           -jvm:java虚拟机,至少占200m内存
          -阿里有自己的jvm

     

    1 redis的hash操作

    from redis import Redis

    conn = Redis()

    # 1 hset(name, key, value)


    # conn.hset('hash_test','name','lqz')
    # conn.hset('hash_test','age','19')

    # name对应的hash中设置一个键值对(不存在,则创建;否则,修改)


    # 2 hmset(name, mapping)
    # conn.hmset('hash_test1',{'name':'egon','age':18})


    # 3 hget(name ,key)

    # print(conn.hget('hash_test1','name'))


    # 4 hmget(name, keys, *args)
    # print(conn.hmget('hash_test1',['name','age']))



    # 5 hgetall(name)

    # print(conn.hgetall('hash_test1')) # 尽量少执行,慢长命令,可能会撑爆应用程序的内容


    # 6 hlen(name)

    # print(conn.hlen('hash_test1'))

    # 获取name对应的hash中键值对的个数


    # 6 hkeys(name)

    # print(conn.hkeys('hash_test1'))

    # 获取name对应的hash中所有的key的值
    # 7 hvals(name)

    # print(conn.hvals('hash_test1'))

    # 获取name对应的hash中所有的value的值
    # 8 hexists(name, key)

    # print(conn.hexists('hash_test1','hobby'))
    # print(conn.hexists('hash_test1','name'))

    # 检查name对应的hash是否存在当前传入的key
    # 9 hdel(name ,*keys)

    # conn.hdel('hash_test1','name','wife')

    # 将name对应的hash中指定key的键值对删除
    # print(re.hdel('xxx' ,'sex' ,'name'))


    # 10 hincrby(name, key, amount=1)

    # conn.hincrby('hash_test1','age',amount=10)

    # 自增name对应的hash中的指定key的值,不存在则创建key=amount
    # 参数:
    # name,redis中的name
    # key, hash对应的key
    # amount,自增数(整数)
    # 11 hincrbyfloat(name, key, amount=1.0)

    # conn.hincrbyfloat('hash_test1','age',1.2) # 存在精度损失问题



    # 12 hscan(name, cursor=0, match=None, count=None)
    # for i in range(1000):
    #     conn.hset('test','%s-%s'%('key',i),i)

    # res=conn.hscan('test',cursor=0,count=100)
    # print(res)
    # print(len(res[1]))
    #
    # res=conn.hscan('test',cursor=res[0],count=100)
    # print(res)
    # print(len(res[1]))



    # 13hscan_iter(name, match=None, count=None)


    # hgetall---》一次性全取出来   ----》生成器用的位置
    for item in conn.hscan_iter('test',count=10):   # 取出全部的value值,但是每次取10个
       print(item)



    conn.close()

     

    2 redis的列表操作

    from redis import Redis

    conn = Redis()
    # 1 lpush(name ,values)
    # conn.lpush('list_test','egon')
    # conn.lpush('list_test','lqz')
    # conn.rpush('list_test','ylf')


    # 2 lpushx(name ,value)

    # 在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边

    # conn.lpushx('yyyyy' ,'egon')
    # conn.lpushx('list_test' ,'egon')

    # 3 llen(name)

    # print(conn.llen('list_test'))

    # name对应的list元素的个数
    # 4 linsert(name, where, refvalue, value))

    # conn.linsert('list_test','before','lqz','dlrb')
    # conn.linsert('list_test','after','lqz','jason')


    # 在name对应的列表的某一个值前或后插入一个新值

    # 参数:
    # name,redis的name
    # where,BEFORE或AFTER(小写也可以)
    # refvalue,标杆值,即:在它前后插入数据(如果存在多个标杆值,以找到的第一个为准)
    # value,要插入的数据

    # 5 r.lset(name, index, value)


    # conn.lset('list_test',0,'xxxx')

    # 对name对应的list中的某一个索引位置重新赋值

    # 参数:
    # name,redis的name
    # index,list的索引位置
    # value,要设置的值

    # 5 r.lrem(name, value, num)

    # conn.lrem('list_test',value='egon',count=1)


    # 在name对应的list中删除指定的值

    # 参数:
    # name,redis的name
    # value,要删除的值
    # num, num=0,删除列表中所有的指定值;
    # num=2,从前到后,删除2个;
    # num=-2,从后向前,删除2个


    # 6 lpop(name)

    # print(conn.lpop('list_test'))

    # print(conn.rpop('list_test'))

    # 在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素

    # 更多:
    # rpop(name) 表示从右向左操作
    # 6 lindex(name, index)
    # print(conn.lindex('list_test',3))


    # 在name对应的列表中根据索引获取列表元素
    # 7 lrange(name, start, end)

    # print(conn.lrange('list_test', 0, 2))

    # 在name对应的列表分片获取数据
    # 参数:
    # name,redis的name
    # start,索引的起始位置
    # end,索引结束位置 print(re.lrange('aa',0,re.llen('aa')))
    # 8 ltrim(name, start, end)


    # conn.ltrim('list_test',0,1)   #保留0-1之间的
    # 在name对应的列表中移除没有在start-end索引之间的值
    # 参数:
    # name,redis的name
    # start,索引的起始位置
    # end,索引结束位置(大于列表长度,则代表不移除任何)




    # 9 rpoplpush(src, dst)

    # 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
    # 参数:
    # src,要取数据的列表的name
    # dst,要添加数据的列表的name





    ###记住
    # 10 blpop(keys, timeout)
    print(conn.blpop('list_test'))


    # 11 r.brpop(keys, timeout),从右向左获取数据

     

    3 其他操作




    # 公共操作,跟类型无关

    from redis import Redis

    conn=Redis()




    # 1 delete(*names)

    # conn.delete('name','age','test')


    # 2 exists(name)

    # res=conn.exists('hash_test','hash_test1')
    # print(res)

    # 检测redis的name是否存在



    # 3 keys(pattern='*')

    # res=conn.keys('h?sh_test') # 慎用
    # res=conn.keys('hash_*') # 慎用
    # print(res)
    # 根据模型获取redis的name

    # 更多:
    # KEYS * 匹配数据库中所有 key 。
    # KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
    # KEYS h*llo 匹配 hllo 和 heeeeello 等。
    # KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo
    # 4 expire(name, time)
    # conn.expire('hash_test',5)
    # 为某个redis的某个name设置超时时间


    # 5 rename(src, dst)

    # conn.rename('hash_test1','xxx')
    # 对redis的name重命名为


    # 6 move(name, db))
    # conn.move('xxx',1)
    # 将redis的某个值移动到指定的db下


    # 7 randomkey()
    # print(conn.randomkey())

    # 随机获取一个redis的name(不删除)


    # 8 type(name)


    # print(conn.type('name'))
    # print(conn.type('list'))

    4 管道


    '''
    1 非关系型数据库,本身不支持事务
    2 redis中的管道可以实现事务的支持(要么都成功,要么都失败)
      -实现的原理:多条命令放到一个管道中,一次性执行

    3 具体代码
    4 如果是集群环境,不支持管道

    '''

    import redis

    pool = redis.ConnectionPool()

    r = redis.Redis(connection_pool=pool)

    pipe = r.pipeline(transaction=True)  # 开启事务

    pipe.multi()    #管道等待放入多条命令
    pipe.set('name', 'egon')


    pipe.set('role', 'admin')

    # 到此,命令都没有执行
    pipe.execute() #执行管道中的所有命令

     

    5 django中使用redis

    方式一(通用方式,任何框架都可以用)

    # 写一个pool
    from redis import ConnectionPool

    POOL = ConnectionPool(max_connections=5, host='127.0.0.1', port=6379)

    # 在使用的位置,获取连接,获取数据
    from luffyapi.libs.redis_pool import POOL
    from redis import Redis
    conn = Redis(connection_pool=POOL)
    name = conn.get('name')

    第二种:django框架专用

    1 pip install django-redis
    2 在配置文件中配置
    CACHES = {
       "default": {
           "BACKEND": "django_redis.cache.RedisCache",
           "LOCATION": "redis://127.0.0.1:6379",
           "OPTIONS": {
               "CLIENT_CLASS": "django_redis.client.DefaultClient",  #这句指的是django中的缓存也缓存到redis中了
               "CONNECTION_POOL_KWARGS": {"max_connections": 100}   #连接池的大小
               # "PASSWORD": "123",
          }
      }
    }

    3 在使用的位置
    conn=get_redis_connection()  # 从连接池中取一个连接
    name = conn.get('name')

    # 这个好,他可以缓存任意对象
    from django.core.cache import cache
    cache.set('user',user)
    cache.get()

    4 以后django中都用这种,好处是django中的缓存也会放到redis中

     

    6 接口缓存

    # 以首页轮播图为例,加入缓存,后期所有接口都可使用缓存
    # 用户来了,先去缓存中看,如果有直接返回,如果没有,去mysql中查,查完以后在缓存中放一份
    # 双写一致性:处理方案有三种
    -只要插入数据,就删除缓存
    class BannerView(ViewSetMixin, ListAPIView):


    queryset = Bannder.objects.all().filter(is_show=True, is_delete=False).order_by('-orders')[0:settings.BANNER_SIZE]
    serializer_class = BannerSerializer

    def list(self, request, *args, **kwargs):
    banner_list = cache.get('banner_cache_list')
    if not banner_list: # 没有值,走它,去数据库查
    response = super().list(request, *args, **kwargs)
    # 在缓存中放一份
    cache.set('banner_cache_list', response.data)
    else:
    # 走了缓存,速度很快
    print('走了缓存')

    response = Response(data=banner_list)
    return response

     

    7 celery介绍

    1 celery:芹菜,分布式的异步任务框架
    2 可以做的事,我们用它来解决什么问题
    - 异步任务 (异步的执行这个任务函数)
    - 延迟任务(延迟5s钟,执行一个任务(函数))
    - 定时任务(定时的执行任务(函数))如果单纯执行定时任务,没必要用 celery,可以使用别的
    3 平台问题
    Celery is a project with minimal funding, so we don’t support Microsoft Windows. Please don’t open any issues related to that platform
    4 读一下
    """
    1)可以不依赖任何服务器,通过自身命令,启动服务(内部支持socket)
    2)celery服务为为其他项目服务提供异步解决任务需求的
    注:会有两个服务同时运行,一个是项目服务,一个是celery服务,项目服务将需要异步处理的任务交给celery服务,celery就会在需要时异步完成项目的需求

    人是一个独立运行的服务 | 医院也是一个独立运行的服务
    正常情况下,人可以完成所有健康情况的动作,不需要医院的参与;但当人生病时,就会被医院接收,解决人生病问题
    人生病的处理方案交给医院来解决,所有人不生病时,医院独立运行,人生病时,医院就来解决人生病的需求
    """

    5 Celery的架构由三部分组成,
    -消息中间件(message broker)
    -Celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成。包括,RabbitMQ, Redis等等
    -任务执行单元(worker)
    -Worker是Celery提供的任务执行的单元,worker并发的运行在分布式的系统节点中
    -任务执行结果存储(task result store)
    -Task result store用来存储Worker执行的任务的结果,Celery支持以不同方式存储任务的结果,包括AMQP, redis等

     

    8 简单使用

    1 pip install celery
    2 两种目录组织结构
    -普通的
    -包管理的(推荐的)
    3 普通的(就一个py文件)

    celery -A proj worker -l INFO
    celery -A celery_task worker -l info -P eventlet

    4 基本使用

    8.1 基本使用

    # 第一步:定义一个py文件(名字随意,我们叫celery_tase)
    from celery import Celery
    backend = 'redis://127.0.0.1:6379/1'
    broker = 'redis://127.0.0.1:6379/2'
    app = Celery(__name__,broker=broker,backend=backend)
    # 被它修饰,就变成了celery的任务
    @app.task
    def add(a,b):
    return a+b

    #第二步:提交任务(新建一个py文件:submit_task)
    from celery_task import add
    # 异步调用
    # 只是把任务提交到了redis中,但是没有执行,返回一个唯一标识,后期使用唯一标识去看任务执行结果
    res=add.delay(33,41)
    print(res)

    #第三步:启动worker
    #celery_task py文件的名字
    #-l info日志输出级别是info
    # -P eventlet 在win平台需要加上
    celery -A celery_task worker -l info -P eventlet
    #如果队列里有任务,就会执行,如果没有任务,worker就等在这

    # 第四步:查询结果是否执行完成
    from celery_task import app

    from celery.result import AsyncResult

    id = 'ed85b97a-a231-4d71-ba11-e5f6450d0b47'
    if __name__ == '__main__':
    a = AsyncResult(id=id, app=app)
    if a.successful():
    result = a.get()
    print(result)
    elif a.failed():
    print('任务失败')
    elif a.status == 'PENDING':
    print('任务等待中被执行')
    elif a.status == 'RETRY':
    print('任务异常后正在重试')
    elif a.status == 'STARTED':
    print('任务已经开始被执行')

    8.2 包管理结构

    1 包结构
    celery_task
    __init__.py
    celery.py
    course_task.py
    home_task.py
    user_task.py
    2 celery.py

    from celery import Celery
    backend = 'redis://127.0.0.1:6379/1'
    broker = 'redis://127.0.0.1:6379/2'
    app = Celery(__name__, broker=broker, backend=backend,
    include=['celery_task.course_task', 'celery_task.user_task', 'celery_task.home_task'])

    3 home_task.py
    from .celery import app
    @app.task
    def add(a,b):
    import time
    time.sleep(10)
    return a+b
    4 在任意项目中使用
    -导入,之间使用,例如
    def test(request):
    # 提交一个计算 90+80的任务
    from celery_task.home_task import add
    res=add.delay(90,80)
    return HttpResponse('任务已经提,任务id为:%s'%str(res))
  • 相关阅读:
    端口扫描器的几种代码实现方案
    滴滴推理引擎IFX:千万规模设备下AI部署实践
    报名啦!第四届滴滴-IEEE未来精英论坛今夏来袭
    torch单机多卡重点:
    常见异常总结,入职阿里巴巴大概率面试题!!!
    龙小树 | R语言学习参考用书推荐
    英文写作常用网址
    LaTeX常用链接与资料
    LaTeX:算法模板
    崩溃中!我终于看明白了,什么是财富自由的底层逻辑!思维导图+笔记精华
  • 原文地址:https://www.cnblogs.com/DEJAVU888/p/14893987.html
Copyright © 2011-2022 走看看