redis模块
Posted eat&
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis模块相关的知识,希望对你有一定的参考价值。
redis模块用于调用操作redis,而redis是一个基于内存的高性能key-value的存储系统,支持存储的类型有string、list、set、zset和hash。在处理大规模数据读写或高效的缓存的场景下运用比较多。
redis模块中实现了两个类来操作数据库,分别是Redis和StricRedis
redis模块中允许两种连接方式直接连接和连接池连接
连接池的原理是,通过预先创建多个连接, 当进行redis操作时,直接获取已经创建的连接进行操作,而且操作完成后,不会释放,用于后续的其他redis操作,这样就达到了避免频繁的redis连接创建和释放的目的,从而提高性能。redis模块采用ConnectionPool来管理对redis server的所有连接。
# 以StricRedis举例 from redis import StrictRedis, ConnectionPool # 直接连接 # 使用默认方式连接到数据库 redis = StrictRedis(host=‘localhost‘, port=6379, db=0) # 使用url方式连接到数据库 redis = StrictRedis.from_url(‘redis://@localhost:6379/1‘) # 连接池连接 # 使用默认方式连接到数据库 pool = ConnectionPool(host=‘localhost‘, port=6379, db=0) redis = StrictRedis(connection_pool=pool) # 使用url方式连接到数据库 pool = ConnectionPool.from_url(‘redis://@localhost:6379/1‘) redis = StrictRedis(connection_pool=pool)
有三种构造url的方式:
redis://[:password]@host:port/db # TCP连接 rediss://[:password]@host:port/db # Redis TCP+SSL 连接 unix://[:password]@/path/to/socket.sock?db=db # Redis Unix Socket 连接
redis中有五种数据类型:字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(sorted set)
哈希是一个string类型的field和value的映射表,hash特别适合用于存储对象。
列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部或者尾部。
集合是String类型的无序集合。集合成员是唯一的,意味着集合中不能出现重复的数据。
有序集合和集合大致相同,不同的是每个元素都会关联一个double类型的分数。通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。
默认情况下,响应以 Python3 的字节Python 2 的 str 形式返回,用户负责解码操作。
String类型操作:
1. set(name, value):设置成功返回True
# 在Redis中设置值,默认不存在则创建,存在则修改
set(name, value, ex=None, px=None, nx=False, xx=False)
# 参数:
# ex-过期时间(秒)
# px-过期时间(毫秒)
# nx-如果设置为True,则只有key不存在时,当前set操作才执行,同#setnx(key, value)
# xx-如果设置为True,则只有key存在时,当前set操作才执行
2. mset(*args, **kwargs)
# 批量设置值 redis.mset({"key1":‘value1‘, "key2":‘value2‘})
3. get(name):返回获取到的值
# 获取某个key的值 redis.get(‘key1‘)
4. mget(keys, *args):返回获取到的值列表
# 批量获取 redis.mget("key1","key1")
5. strlen(name)
# 返回key对应值的字节长度(一个汉字3个字节) redis.strlen("key")
6. append(name, value)
# 在name对应的值后面追加内容 redis.set("key","value") print(redis.get("key")) # 输出:‘value‘ redis.append("key","one") print(redis.get("key")) # 输出:‘valueone‘
7. substr(name, start, end=-1)
# key为name的string的value的子串,start为起始索引,end为结束索引 redis.set(‘key‘,‘value‘) redis.substr(‘key‘, 1, 4) # 输出‘alue’
8. getrange(key, start, end)
# 获取key的value值从start到end的子字符串 redis.set("key", "value") redis.getrange(‘key‘, 1, 4) # 输出 ‘alue‘
9. getset(name, value):给数据库中key为name的string赋予值value并返回上次的value
10. setnx(name, value):如果key不存在才设置value,操作成功返回True
11. setex(name, time, value):设置可以对应的值为string类型的value,并指定此键值对应的有效期(秒),操作成功返回True
12. setrange(name, offset, value):设置指定key的value值的子字符串,返回修改后的字符串长度
13. msetnx(mapping):key均不存在时才批量赋值,操作成功返回True
14. incr(name, amount=1):key为name的value增值操作,默认1,key不存在则被创建并设为amount,返回修改后的值
15. decr(name, amount=1):key为name的value减值操作,默认1,key不存在则被创建并设置为-amount,返回修改后的值
Hash类型操作:
1. hset(name, key, value):返回键值对添加个数
# name对应的hash中设置一个键值对(不存在,则创建,否则,修改) redis.hset("name","key","value")
2. hget(name, key)
redis.hset("name","key","value") # 在name对应的hash中根据key获取value print(redis.hget("name","key")) # 输出:‘value‘
3. hgetall(name)
# 获取name所有键值对 redis.hgetall("name")
4. hmset(name, mapping)
# 在name对应的hash中批量设置键值对,mapping:字典 dic={"key1":"aa","key2":"bb"} redis.hmset("name",dic) print(redis.hget("name","key2")) # 输出:bb
5. hmget(name, keys, *args)
# 在name对应的hash中批量获取键所对应的值 dic={"key1":"aa","key2":"bb"} redis.hmset("name",dic) print(redis.hmget("name","key1","key2")) # 输出:[‘aa‘, ‘bb‘]
6. hlen(name)
# 获取hash键值对的个数 print(redis.hlen("name")) # 输出:2
7. hkeys(name)
# 获取hash中所有key redis.hkeys("name")
8. hvals(name)
# 获取hash中所有value redis.hvals("name")
9. hexists(name, key)
# 检查name对应的hash是否存在当前传入的key print(redis.hexists("name","key1")) # 输出:Ture
10. hdel(name, *keys)
# 删除指定name对应的key所在的键值对,删除成功返回1,失败返回0 print(redis.hdel("name","key1")) # 输出:1
11. hincrby(name, key, amount=1)
# 与hash中key对应的值相加,不存在则创建key=amount(amount为整数)
print(redis.hincrby("name","key",amount=10)) # 返回:10
12. hsetnx(name, key, value):向key为name的hash中添加映射,如果映射键名不存在执行,返回添加键值对的个数
list类型操作:
1. lpush(name, *values)
# 元素从list的左边添加,可以添加多个 redis.lpush(‘name‘,‘元素1‘,‘元素2‘)
2. rpush(name, *values)
# 元素从list右边添加,可以添加多个 redis.rpush(‘name‘,‘元素1‘,‘元素2‘)
3. lpushx(name, *values)
# 当name存在时,元素才能从list的左边加入 redis.lpushx(‘name‘,‘元素1‘)
4. rpushx(name, *values)
# 当name存在时,元素才能从list的右边加入 redis.rpushx(‘name‘,‘元素1‘)
5. llen(name)
# name列表长度 redis.llen(‘name‘)
6. linsert(name, where, refvalue, value)
# 在name对应的列表的某一个值前或后插入一个新值
redis.linsert("name","BEFORE","元素2","元素1.5")#在列表内找到第一个"元素2",在它前面插入"元素1.5" # 参数: # name: redis的name # where: BEFORE(前)或AFTER(后) # refvalue: 列表内的值 # value: 要插入的数据
7. lset(name, index, value)
# 对list中的某一个索引位置重新赋值, 越界则报错 redis.lset("name",0,"abc")
8. lrem(name, value, num=0)
# 删除name对应的list中的指定值 redis.lrem("name","元素1",num=0) # 参数: # name: redis的name # value: 要删除的值 # num: num=0 删除列表中所有的指定值 # num=2 从前到后,删除2个 # num=-2 从后向前,删除2个
9. lpop(name):rpop(name)移除右侧第一个元素
# 移除列表的左侧第一个元素,返回值则是第一个元素 print(redis.lpop("name"))
10. lindex(name, index)
# 根据索引获取列表内元素 print(redis.lindex("name",1))
11. lrange(name, start, end)
# 分片获取元素 print(redis.lrange("name",0,-1))
12. ltrim(name, start, end)
# 移除列表内没有在该索引之内的值 redis.ltrim("name",0,2)
13. blpop(name, timeout=0):返回并删除名称为在keys中的list中的首元素,如果list为空,则会一直阻塞等待
14. brpop(name, timeout=0):返回并删除key为name的list中的尾元素,如果list为空,则会一直阻塞等待
15. rpoplpush(src, dst):返回并删除名称为src的list的尾元素,并将该元素添加到名称为dst的list的头部
set类型操作:
1. sadd(name, *values)
# 给name对应的集合中添加元素 redis.sadd("name","aa") redis.sadd("name","aa","bb")
2. scard(name)
# 获取name对应的集合中的元素个数 redis.scard("name")
3. smembers(name)
# 获取name对应的集合的所有成员 redis.smembers(‘name‘)
4. sdiff(keys, *args):返回所有给定key的set的差集
# 在第一个name对应的集合中且不在其他name对应的集合的元素集合 redis.sadd("name","aa","bb") redis.sadd("name1","bb","cc") redis.sadd("name2","bb","cc","dd") print(red.sdiff("name","name1","name2"))#输出:{aa}
5. sismember(name, value) :检查value是否是name对应的集合内的元素
6. smove(src, dst, value):将某个元素从一个集合中移动到另外一个集合
7. spop(name):随机返回并删除key为name的set中一个元素
8. srem(name, *values):从key为name的set中删除元素
9. sinter(keys, *args):返回所有给定key的set的交集
10. sinterstore(dest, keys, *args):求交集并将交集保存到dest的集合
11. sunion(keys, *args):返回所有给定key的set的并集
12. sunionstore(dest, keys, *args):求并集并将并集保存到dest的集合
13. sdiffstore(dest, keys, *args):求差集并将差集保存到dest的集合
14. srandmember(name):随机返回key为name的set的一个元素,但不删除元素
Sorted Set类型操作:
1. zadd(name, args, *kwargs):向key为name的zset中添加元素member,score用于排序。如果该元素存在,则更新其顺序
redis.zadd(‘grade‘, 100, ‘Bob‘, 98, ‘Mike‘)
2. zrem(name, *values):删除key为name的zset中的元素
redis.zrem(‘grade‘, ‘Mike‘)
3. zincrby(name, value, amount=1):如果在key为name的zset中已存在元素value,则该元素的score增加amount,否则向该集合中添加该元素,score的值为amount
4. zrank(name, value):返回key为name的zset中元素的排名(按score从小到大排序)即下标
5. zrevrank(name, value):返回key为name的zset中元素的倒数排名(按score从大到小排序)即下标
6. zrevrange(name, start, end, withscores=False):返回key为name的zset(按score从大到小排序)中的index从start到end的所有元素,默认不带分值
7. zrangebyscore(name, min, max, withscores=False):返回key为name的zset中score在给定区间的元素
8. zcount(name, min, max):返回key为name的zset中score在给定区间的数量
9. zcard(name):返回key为name的zset的元素个数
10. zremrangebyrank(name, min, max):删除key为name的zset中排名在给定区间的元素
11. zremrangebyscore(name, min, max):删除key为name的zset中score在给定区间的元素
其他常用操作:
flushdb(asynchronous=False):清空当前db中的数据,默认是同步。若开启异步asynchronous=True,会新起一个线程进行清空操作,不阻塞主线程
flushall(asynchronous=False):清空所有db中的数据,默认是同步。异步同flushdb
delete(*names):根据name删除redis中的任意数据类型
exists(name):判断一个key是否存在
keys(pattern=‘*‘):根据* ?等通配符匹配获取redis的name,*任意多个字符
expire(name, time):为某个name的设置过期时间,单位秒
rename(src, dst):重命名
move(name, db)):将redis的某个name移动到指定的db下
randomkey():随机获取一个redis的name(不删除)
type(name):获取name对应值的类型
dbsize():获取当前数据库中key的数目
ttl(name):获取key的过期时间,单位秒,-1为永久不过期
RedisDump
redis-load:将数据导入到数据库中
redis-load -h # 获取帮助信息 < redis_data.json redis-load -u redis://@localhost:6379 # 将json数据导入数据库中
redis-dump:将数据库信息导出
redis-dump -h # 获取帮助信息 redis-dump -u redis://@localhost:6379 -d 1 > ./redis.data.jl # 导出到json文件 redis-dump -u redis://@localhost:6379 -f adsl:* > ./redis.data.jl # 导出adsl开头的数据
StricRedis类和Redis类的区别:
StricRedis类
尽量坚持官方语法,除了以下命令:
-
select
没有实现,考虑到了线程安全 -
del
Python 关键字,用delete
代替 -
config get|se
作为config_get / config_set
实现 -
multi / exec
作为Pipeline
类的一部分实现的
Redis
类是 StricRedis
的子类,提供向后的兼容性。推荐使用 StricRedis
。Redis 覆盖了几个命令:
-
lrem
num 和 value 参数顺序颠倒,num 提供默认值 0 -
zadd
Redis类期望* args的形式为:name1,score1,name2,score2,...
,而 StricRedis 是score1,name1,score2,name2,...
,这与 Redis 一样 -
setex
time 和 value 顺序颠倒。在 Redis 类中是:setex(key, value, time)
,在 StricRedis 类中是:setex(key, time, value)
管道
管道一般用来执行事务操作
r = redis.Redis(...) r.set(‘bing‘, ‘baz‘) pipe = r.pipeline() pipe.set(‘foo‘, ‘bar‘) pipe.get(‘bing‘) pipe.execute() # 输出 [True, ‘baz‘]
管道也可进行链式操作
pipe.set(‘ foo ‘,‘ bar ‘).sadd(‘ faz ‘,‘ baz ‘).incr(‘ auto_number ‘).execute() # 输出 [True,True,6]
可禁用原子性:
pipe = r.pipeline(transaction = False)
WATCH 监控命令:
with r.pipeline() as pipe: while 1: try: # 设置一个 watch pipe.watch(‘OUR-SEQUENCE-KEY‘) current_value = pipe.get(‘OUR-SEQUENCE-KEY‘) next_value = int(current_value) + 1 # 开始事务 pipe.multi() pipe.set(‘OUR-SEQUENCE-KEY‘, next_value) # 执行 pipe.execute() # 如果抛出 WatchError ,表示原子性失败 break except WatchError: # 另一个客户端修改了,我们必须重试 continue
由于Pipeline在watch期间绑定到单个连接,必须调用reset()来确保返回连接池,使用with上下文的话,它会自动调用。当然也可以手动调用:
pipe = r.pipeline() while 1: try: pipe.watch(‘OUR-SEQUENCE-KEY‘) ... pipe.execute() break except WatchError: continue finally: pipe.reset()
也可以使用 transaction() 方法来简化操作
def client_side_incr(pipe): current_value = pipe.get(‘OUR-SEQUENCE-KEY‘) next_value = int(current_value) + 1 pipe.multi() pipe.set(‘OUR-SEQUENCE-KEY‘, next_value) r.transaction(client_side_incr, ‘OUR-SEQUENCE-KEY‘) # 输出 [True]
线程安全问题:
可以在线程之间安全地共享 Redis 客户端实例。有一点需要注意:Redis SELECT命令。SELECT命令允许您切换连接当前使用的数据库。该数据库保持选定状态直到选择另一个数据库或连接关闭。这会产生一个问题,即连接可以返回到连接到不同数据库的池。因此不会实现 select 命令。 在线程之间传递PubSub或Pipeline对象是不安全的。以上是关于redis模块的主要内容,如果未能解决你的问题,请参考以下文章
CTS测试CtsWindowManagerDeviceTestCases模块的testShowWhenLockedImeActivityAndShowSoftInput测试fail项解决方法(代码片段