首页 > 数据库 >路飞项目day_10 redis 列表 hash 通用 管道 celery简单操作

路飞项目day_10 redis 列表 hash 通用 管道 celery简单操作

时间:2023-03-08 21:57:39浏览次数:34  
标签:10 hash name redis celery key conn

目录

今日内容详细

一、redis之列表

# 1 lpush(name, values)  在name对应的list中添加元素,每个新的元素都添加到列表的最左边

# 2 rpush(name, values) 表示从右向左操作

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


# 4 rpushx(name, value) 表示从右向左操作

# 5 llen(name)  name对应的list元素的个数

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

# 7 lset(name, index, value)  对name对应的list中的某一个索引位置重新赋值
# 参数:
# name,redis的name
# index,list的索引位置
# value,要设置的值

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

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


# 10 rpop(name) 表示从右向左操作

# 11 lindex(name, index)  在name对应的列表中根据索引获取列表元素

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

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

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

# 15 blpop(keys, timeout)  将多个列表排列,按照从左到右去pop对应列表的元素
# 可以做消息队列使用  阻塞式弹出,如果没有,就阻塞
# 参数:
# keys,redis的name的集合
# timeout,超时时间,当元素所有列表的元素获取完之后,阻塞等待列表内有数据的时间(秒), 0 表示永远阻塞


# 16 brpop(keys, timeout),从右向左获取数据
# 爬虫实现简单分布式:多个url放到列表里,往里不停放URL,程序循环取值,但是只能一台机器运行取值,可以把url放到redis中,多台机器从redis中取值,爬取数据,实现简单分布式

# 17 brpoplpush(src, dst, timeout=0)  从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧
# 参数:
# src,取出并要移除元素的列表对应的name
# dst,要插入元素的列表对应的name
# timeout,当src对应的列表中没有数据时,阻塞等待其有数据的超时时间(秒),0 表示永远阻塞

"""
lpush
lpop
llen
lrange
"""

二、redis之hash

# 1 hset(name, key, value)  name对应的hash中设置一个键值对(不存在,则创建;否则,修改)
# 参数:
# name,redis的name
# key,name对应的hash中的key
# value,name对应的hash中的value

# 2 hsetnx(name, key, value)  当name对应的hash中不存在当前key时则创建(相当于添加)
# 不如hset  只能添加

# 3 hmset(name, mapping)  在name对应的hash中批量设置键值对
# 参数:
# name,redis的name
# mapping,字典,如:{'k1':'v1', 'k2': 'v2'}
# 批量设置,被弃用了,以后都使用hset

# 4 hget(name, key)  在name对应的hash中获取根据key获取value

# 5 hmget(name, keys, *args)  在name对应的hash中获取多个key的值
# 参数:
# name,reids对应的name
# keys,要获取key集合,如:['k1', 'k2', 'k3']
# *args,要获取的key,如:k1,k2,k3

# 6 hgetall(name)  # 慎用
# 会一次性全取出,效率低,可以能占内存很多
# 分批获取,hash类型是无序

# 7 hlen(name)  获取name对应的hash中键值对的个数

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

# 9 hvals(name)  获取name对应的hash中所有的value的值

# 10 hexists(name, key)  检查name对应的hash是否存在当前传入的key

# 11 hdel(name, *keys)  # 将name对应的hash中指定key的键值对删除

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

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

# 14 hscan(name, cursor=0, match=None, count=None)  增量式迭代获取,对于数据大的数据非常有用,hscan可以实现分片的获取数据,并非一次性将数据全部获取完,从而放置内存被撑爆
# 参数:
# name,redis的name
# cursor,游标(基于游标分批取获取数据)
# match,匹配指定key,默认None 表示所有的key
# count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数
# 直到返回值cursor的值为0时,表示数据已经通过分片获取完毕
# 它不单独使用,拿的数据,不是特别准备


# 15 hscan_iter(name, match=None, count=None)  利用yield封装hscan创建生成器,实现分批去redis中获取数据
# 参数:
# match,匹配指定key,默认None 表示所有的key
# count,每次分片最少获取个数,默认None表示采用Redis的默认分片个数
# 它内部用了hscan,等同于hgetall 所有数据都拿出来,count的作用是,生成器,每次拿count个个数
# res=conn.hscan_iter('hash_test',count=10)
# print(res)  # generator 只要函数中有yield关键字,这个函数执行的结果就是生成器 ,生成器就是迭代器,可以被for循环
# for i in res:
#     print(i)

三、redis其他操作

''' 通用操作,不指定类型,所有类型都支持
1 delete(*names)
2 exists(name)
3 keys(pattern='*')
4 expire(name ,time)
5 rename(src, dst)
6 move(name, db))
7 randomkey()
8 type(name)
'''

import redis

conn = redis.Redis()
# 1 delete(*names)
# conn.delete('name', 'userinfo2')
# conn.delete(['name', 'userinfo2'])  # 不能用它
# conn.delete(*['name', 'userinfo2'])  # 可以用它


# 2 exists(name)
# res=conn.exists('userinfo')  1
# res=conn.exists('userinfo2')  0
# print(res)


# 3 keys(pattern='*')
# res=conn.keys('w?e')  #  ?表示一个字符,   * 表示多个字符
# print(res)


# 4 expire(name ,time)   过期时间
# conn.expire('userinfo',3)

# 5 rename(src, dst)
# conn.rename('hobby','hobby111')

# 6 move(name, db))  移到指定的库
# conn.move('hobby111',8)
# 7 randomkey()
# res=conn.randomkey()  随机弹一个key
# print(res)
# 8 type(name)
# print(conn.type('girls'))
print(conn.type('age'))
conn.close()

四、redis管道

# redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。

# redis支持事务吗   单实例才支持所谓的事物,支持事务是基于管道的
	-执行命令  一条一条执行
    	-张三 金额 -100    conn.decr('zhangsan_je',100)
        挂了
        -你   金额 100     conn.incr('李四_je',100)
        
        
   - 把这两条命令,放到一个管道中,先不执行,执行excute,一次性都执行完成
	conn.decr('zhangsan_je',100)   conn.incr('李四_je',100)
    
    
    
# 如何使用
import redis
conn = redis.Redis()
p=conn.pipeline(transaction=True)
p.multi()
p.decr('zhangsan_je', 100)
# raise Exception('崩了')
p.incr('lisi_je', 100)

p.execute()
conn.close()

五、django中使用redis

##  方式一:自定义包方案(通用的,不针对与框架,所有框架都可以用)
	-第一步:写一个pool.py
    import redis
	POOL = redis.ConnectionPool(max_connections=100)
    -第二步:以后在使用的地方,直接导入使用即可
    conn = redis.Redis(connection_pool=POOL)
    conn.incr('count')
    res = conn.get('count')
    
    
    
## 方式二:django 方案,
	-方案一:django的缓存使用redis  【推荐使用】
    	-settings.py 中配置
        CACHES = {
            "default": {
                "BACKEND": "django_redis.cache.RedisCache",
                "LOCATION": "redis://127.0.0.1:6379",
                "OPTIONS": {
                    "CLIENT_CLASS": "django_redis.client.DefaultClient",
                    "CONNECTION_POOL_KWARGS": {"max_connections": 100}
                    # "PASSWORD": "123",
                }
            }
        }
        
       -在使用redis的地方:cache.set('count',  res+1)
       -pickle序列化后,存入的
    
    -方案二:第三方:django-redis模块
    	from django_redis import get_redis_connection
        def test(request):
            conn = get_redis_connection()
            conn.incr('count')
            res = conn.get('count')
            return JsonResponse({'count': f'今天这个接口被访问{res}次'}, json_dumps_params={'ensure_ascii': False})

六、celery介绍和安装

# Celery 是什么
	-翻译过来是  芹菜   的意思,跟芹菜没有关系
	-框架:服务,python的框架,跟django无关
	-能用来做什么
		-1 异步任务
		-2 定时任务
		-3 延迟任务
        
        
# 理解celery的运行原理
"""
1)可以不依赖任何服务器,通过自身命令,启动服务
2)celery服务为为其他项目服务提供异步解决任务需求的
注:会有两个服务同时运行,一个是项目服务,一个是celery服务,项目服务将需要异步处理的任务交给celery服务,celery就会在需要时异步完成项目的需求

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



# celery架构(Broker,backend 都用redis)
	- 1 任务中间件 Broker(中间件),其他服务提交的异步任务,放在里面排队
    	-需要借助于第三方 redis   rabbitmq  
    - 2 任务执行单元 worker     真正执行异步任务的进程
    	-celery提供的
    - 3 结果存储   backend     结果存储,函数的返回结果,存到 backend中 
    	-需要借助于第三方:redis,mysql
        
        
        
        
 # 使用场景
    异步执行:解决耗时任务
    延迟执行:解决延迟任务
    定时执行:解决周期(周期)任务
   


# celery 不支持win,通过eventlet支持在win上运行

七、celery快速使用

# 安装---》安装完成,会有一个可执行文件 celery
	pip install celery
    win:pip install eventlet

    
# 快速使用
######### 第一步:新建 main.py######### 
from celery import Celery
# 提交的异步任务,放在里面
broker = 'redis://127.0.0.1:6379/1'
# 执行完的结果,放在这里
backend = 'redis://127.0.0.1:6379/2'
app = Celery('test', broker=broker, backend=backend)
@app.task
def add(a, b):
    import time
    time.sleep(3)
    print('------',a + b)
    return a + b

######### 第二步:其他程序,提交任务######### 
res = add.delay(5,6)   #原来add的参数,直接放在delay中传入即可
print(res)  # f150d8a5-c955-478d-9343-f3b60d0d5bdb


### 第三步:启动worker
# 启动worker命令,win需要安装eventlet
	win:
       -4.x之前版本
		celery worker -A main -l info -P eventlet
       -4.x之后
    	celery  -A main  worker -l info -P eventlet
	mac:
       celery  -A main  worker -l info
        
        
### 第四步:worker会执行消息中间件中的任务,把结果存起来####


### 第五步:咱们要看执行结果,拿到执行的结果#####
from main import app
from celery.result import AsyncResult
id = '51611be7-4914-4bd2-992d-749008e9c1a6'
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('任务已经开始被执行')

八、celery包结构

project
    ├── celery_task  	# celery包
    │   ├── __init__.py # 包文件
    │   ├── celery.py   # celery连接和配置相关文件,且名字必须交celery.py
    │   └── tasks.py    # 所有任务函数
    ├── add_task.py  	# 添加任务
    └── get_result.py   # 获取结果
    
    
############# 第一步:新建包 celery_task #############
# 在包下新建[必须叫celery]的py文件,celery.py 写代码
from celery import Celery
broker = 'redis://127.0.0.1:6379/1'
backend = 'redis://127.0.0.1:6379/2'
app = Celery('test', broker=broker, backend=backend, include=['celery_task.order_task', 'celery_task.user_task'])


##### 第二步:在包内部,写task,任务异步任务####
# order_task
from .celery import app
import time
@app.task
def add(a, b):
    print('-----', a + b)
    time.sleep(2)
    return a + b

# user_task
from .celery import app
import time
@app.task
def send_sms(phone, code):
    print("给%s发送短信成功,验证码为:%s" % (phone, code))
    time.sleep(2)
    return True

####第三步:启动worker ,包所在目录下
	celery  -A celery_task  worker -l info -P eventlet
    
    
###第四步:其他程序 提交任务,被提交到中间件中,等待worker执行,因为worker启动了,就会被worker执行
from celery_task import send_sms
res=send_sms.delay('1999999', 8888)
print(res)  # 7d39033c-4cc7-4af2-8d78-e62c277db183


### 第五步:worker执行完,结果存到backend中

### 第六步:我们查看结构
from celery_task import app
from celery.result import AsyncResult
id = '7d39033c-4cc7-4af2-8d78-e62c277db183'
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('任务已经开始被执行')

标签:10,hash,name,redis,celery,key,conn
From: https://www.cnblogs.com/qian-yf/p/17196391.html

相关文章