1 redis列表操作
import redis
conn = redis.Redis(decode_responses=True)
1 lpush(name,values)
# 在name对应的list中添加元素,每个新的元素都添加到列表的最左边
# rpush(name, values) 表示从右向左操作
# 如果name不存在的话会新增name
conn.lpush('hobbys', '篮球')
conn.lpush('hobbys', '足球')
conn.lpush('hobbys', '乒乓球')
2 lpushx(name,value)
# 在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边
# rpushx(name, value) 表示从右向左操作
conn.lpushx('hobbys1', '排球')
3 llen(name)
# name对应的list元素的个数
print(conn.llen('hobbys'))
4 linsert(name, where, refvalue, value)
# 在name对应的列表的某一个值前或后插入一个新值
# 参数
'''
name,redis的name
where,BEFORE或AFTER(小写也可以)
refvalue,标杆值,即:在它前后插入数据(如果存在多个标杆值,以找到的第一个为准)
value,要插入的数据
'''
conn.linsert('hobbys', 'after', '乒乓球', '保龄球')
conn.linsert('hobbys', 'before', '乒乓球', '球球')
5 lset(name, index, value)
# 对name对应的list中的某一个索引位置重新赋值
conn.lset('hobbys', 1, '球球球')
6 lrem(name,num, value )
# 在name对应的list中删除指定的值
# conn.lrem('hobbys',0,'排球') # 0 表示全删除
# conn.lrem('hobbys', 1, '足球') # 正数表示从左侧删除num个
# conn.lrem('hobbys', -2, '足球') # 负数表示从右侧删除num个
7 lpop(name)
# 在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素
# rpop(name) 表示从右向左操作
print(conn.lpop('hobbys')) # 从左侧弹出
print(conn.rpop('hobbys'))
8 lindex(name, index)
# 在name对应的列表中根据索引获取列表元素
res=conn.lindex('hobbys',2)
print(res)
9 lrange(name, start, end)
# 在name对应的列表分片获取数据
res=conn.lrange('hobbys',0,2) # 前闭后闭区间
print(res)
10 ltrim(name, start, end)
# 在name对应的列表中移除没有在start-end索引之间的值
res=conn.ltrim('hobbys',1,3)
print(res)
11 rpoplpush(src, dst)
# 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边
# 参数:
# src,要取数据的列表的name
# dst,要添加数据的列表的name
12 blpop(keys, timeout)
# 这个就是简单的消息队列,可以实现分布式的程序----》生产者消费者模型
# 将多个列表排列,按照从左到右去pop对应列表的元素
res=conn.blpop('hobby',timeout=2) # 只要列表中没有值,就会阻塞,有值才会继续运行,0 表示永远阻塞
print(res)
13 brpoplpush(src, dst, timeout=0)
# 从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧
# 参数:
# src,取出并要移除元素的列表对应的name
# dst,要插入元素的列表对应的name
# timeout,当src对应的列表中没有数据时,阻塞等待其有数据的超时时间(秒),0 表示永远阻塞
'''自定义增量迭代'''
# 一次性把列表中所有数据取出来【分批拿,防止内存撑爆】
# 造数据
for i in range(1000):
conn.lpush('eggs','鸡蛋%s号'%i)
l=conn.llen('eggs')
res=conn.lrange('eggs',0,l)
print(res)
# 生成器的作用:减少内存占用,惰性求值
def l_scan_iter(key, count=10):
num = 0
while True:
print('-----------')
res = conn.lrange(key, num, num + count - 1)
num = num + count
if res:
for item in res:
yield item
else:
break
for item in l_scan_iter('eggs', 20):
print(item)
conn.close()
'''
lpush
lpop
linsert
lset
llen
lrange
'''
# 设置缓存后取不到的问题:
做了一个集群,布了多台机器,把数据缓存在内存中,第一次去服务器A,验证码缓存在A的内存,第二次去服务器B,内存没有缓存数据,就找不到数据。
解决方法:将数据缓存在redis中,共享缓存
补充
# 集群和分布式
集群:同一个项目布在多台机器上或让它运行多次。集群指的是将多台计算机连接在一起,形成一个统一的计算资源池,通过协同工作来提供更高的计算能力和可靠性
分布式:指的是将一个任务或服务拆分成多个子任务,分别由不同的计算机节点来处理。每个节点独立地执行自己的任务,并通过相互通信来协调工作,最终将结果合并起来。微服务就是分布式的一种。
# 分布式程序的应用:
其他语言写的程序产生了很多日志,日志不是存到日志文件里,而是直接丢到一个消息队列卡夫卡里,目前可以理解为丢到redis的列表中。我们就可以写一个python程序,从消息队列里取日志并且分析,留下有用的。
本来一个程序把这件事完成,现在用多个语言完成一件事【跨语言之间通信】,这就叫分布式程序。
# 消息队列
redis做消息队列性能不高,专业的消息队列有RabbitMQ或者是卡夫卡这些东西,但是redis可以实现。
# 生产者消费者模型
people1在造包子放在盘子里,people2从盘子里拿包子吃,redis列表就是这个盘子。people1【可能很多线程或进程】造数据放在redis列表里,people2【可能很多线程或进程】。1造2取,如果盘子里没有数据,2就等待。这样就能做成简单的分布式。
# eg:爬虫正常流程一条线:爬取数据----》解析数据----》传入数据库。实际上爬取的时候非常慢,解析和入库速度很快。我们就可以把这一条件拆解为2部分,一部分专门爬,另一部分解析入库。爬的时候爬完把爬完的数据放到列表中,别的线程也好进程也好,从列表中取得数据解析入库。这样的话我爬的线程开50个,解析的线程开2个,就叫分布式的程序,跟连爬到取一条线布50次是不一样的。如果连爬到取一条线布50次是集群化的部署。
'''
异步和分布式是两个不同的概念,它们在计算领域中有不同的应用和含义。
异步(Asynchronous)是一种编程模型,用于处理任务的执行方式。在异步编程中,任务并发执行,可以在等待某些操作完成时继续执行其他任务,而不需要阻塞整个程序。异步编程通常适用于处理耗时的 I/O 操作或并发任务,以提高程序的性能和响应能力。
分布式(Distributed)是一种架构或计算模型,用于组织和管理计算资源。在分布式计算中,任务和数据可以在多个计算节点或计算机之间分布和执行。这种架构允许并行处理和处理大规模的计算工作负载。分布式系统通常由多个资源节点和协调器组成,并使用网络协议进行通信和协调。
简而言之,异步关注的是任务执行的方式和流程,以提高性能和响应能力,而分布式关注的是计算资源的组织和协调方式,以实现并行处理和处理大规模的工作负载。
然而,异步和分布式可以在某些情况下一起使用。例如,在分布式系统中,并行执行的任务可以使用异步编程模型来处理,以提高整个系统的性能和吞吐量。
'''
2 redis其它操作
import redis
conn=redis.Redis()
1 delete(*names)
# 删除redis中的任意数据类型
conn.delete('eggs','hobbys')
2 exists(name)
# 检测redis的name是否存在
conn.set('name','lqz')
print(conn.exists('name'))
3 keys(pattern='*')
# 根据模型获取redis的name
res=conn.keys('*') # *多个字符 ?单个字符
res=conn.keys('nam?')
print(res)
4 expire(name ,time)
# 为某个redis的某个name设置超时时间
conn.expire('hobby',5)
5 rename(src, dst)
# 对redis的name重命名为
conn.rename('name','name1')
6 move(name, db)
# 将redis的某个值移动到指定的db下
conn.move('name1',2)
7 randomkey()
# 随机获取一个redis的name(不删除)
res=conn.randomkey()
print(res)
8 type(name)
# 获取name对应值的类型,不存在就是none
res=conn.type('name1')
print(res)
conn.close()
3 redis管道
# 事务四大特性
-原子性(Atomicity):事务一旦提交,要么都成功,要么都失败
-一致性(Consistency):数据前后要一致
-隔离性(Isolation):多个事务之间相互不影响
-持久性(Durable):事务一旦提交,数据永久改变,不可回滚
# 事务的隔离级别
# 未提交读(READ UNCOMMITTED)
事务的最低级别,会造成脏读、不可重复读、幻读
# 已提交读(READ COMMITTED)
该级别解决了脏读,但不可重复读和幻读任然存在
# 可重复读(REPEATABLE READ)
该级别是mysql5.7版本后默认的事务级别,该级别解决了脏读、不可重复读
# 串行化(SERIALIZABLE)
事务的最高级别,解决了脏读、不可重复读、幻读,该级别极大的保证了数据的安全性,缺点是无并发可言
# 脏读、不可重复读、幻读
# 脏读
指A在事务的过程中可以读取到B修改单位提交的数据
# 不可重复读
指在同一个事务中,多次读出数据,出现数据不一致的情况,这种情况通常是update和delete(数据前后不一致或开始时候读取存在,后来就消失了)
# 幻读
很多人会把幻读和不可重复读混淆,幻读指在同一个事务的过程中,多次读取数据时,出现了新的数据(insert)
# 解决办法
# 机制锁:
ru:最低级别,不加锁
rc:开启事务时加行级锁,读到的时候加锁,读取完毕释放锁
rr:开启事务时加行级锁,关闭事务时释放
se:开启事务加表锁,关闭事务释放锁
# MVCC机制:
保存某个时间上的数据快照
# mysql有哪些索引类型及作用
# 首先先说一下什么是索引及索引的作用:
在关系型数据库中,给一个或多个字段(联合索引)设置索引,可以加快数据检索(类似于目录),达到快速查找的作用
# 普通索引:允许该字段出现重复的值,且可以为空
# 唯一索引:不允许该字段出现重复值,且不可以为空
# 主键索引:非空且唯一,在不主动生成的情况下数据库会默认生成一个字段为主键(一般是id字段),非空且唯一
# 联合索引:多个字段联合唯一
# 全文索引:所有字段都作为索引条件,一般用的比较少,如果删除或修改字段可能照成B树结构改变,在数据量庞大的情况下不建议使用(主要根据业务逻辑来判断是否使用)
# redis 有没有事务?支持事务
-redis要支持事务,要完成事务的几大特性,需要使用管道来支持
-单实例redis是支持管道的
-集群模式下,不支持管道,就不支持事务
# redis通过管道实现事务
import redis
conn = redis.Redis()
pipline = conn.pipeline(transaction=True)
pipline.decrby('a1', 10) # 没有真正执行,把命令先放到管道中
raise Exception('出错了')
pipline.incrby('a2', 10)
pipline.execute() # 把管道中的命令,一次性执行
conn.close()
4 django中使用redis
# 两种方式
# 方式一:自定义的通用方案(跟框架无关)
-写一个py文件:redis_pool.py
import redis
POOL=redis.ConnectionPool(max_connections=10)
-在用的位置,导入直接使用
conn = redis.Redis(connection_pool=POOL)
conn.incrby('a1')
# 方式二:django中有个模块,django-redis,方便我们快速集成redis
1 下载:pip install django-redis
2 配置文件配置:
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",
}
}
}
'''
这段代码是用于配置Django缓存的设置。具体来说,它将默认缓存设置为使用Redis作为后端,并指定了Redis服务器的位置为127.0.0.1:6379(本地端口为6379)。还设置了一些可选项,包括使用默认的Redis客户端类和连接池参数。你看到的# "PASSWORD": "123",是一个注释行,用于说明如何设置Redis的密码。在当前设置中,该行被注释掉,即没有设置Redis密码。
'''
3 在使用的地方,导入直接使用
from django_redis import get_redis_connection
class MyResponseView(APIView):
def get(self, request):
conn = get_redis_connection() # 从连接池中拿出一个链接
conn.incrby('a1')
conn.set('name','彭于晏')
return APIResponse()
5 django缓存
# django 是大而全的框架,内置了很多web开发需要的东西,缓存内置了
# 缓存:可以把django中的一个变量(数据),存放到某个位置,下次还可以取出来
# 之前用过:默认放在:内存中,其实可以放在文件中,数据库,redis。。。。
from django.core.cache import cache
cache.set('key','value',5) # 存放值
res=cache.get('key') # 取值
# 通过配置,控制存放在哪,只要如下写,就会放在redis中
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",
}
}
}
# django缓存最强大之处在于,只要是python的变量,任意类型都可以,尽管使用set设置值
l = [1, 'lqz', [1, 3, 4, 5, 6], '彭于晏']
cache.set('ll1', l)
# 以后在django中往redis放数据,就用cache即可
# redis的5大数据类型,只支持一层
# 看一下这篇文章:
# Django缓存,前后端分离用cache,前后端混合关注下面链接
标签:10,name,hobbys,res,redis,列表,路飞,conn
From: https://www.cnblogs.com/10086upup/p/17514475.html