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模块的主要内容,如果未能解决你的问题,请参考以下文章

如何有条件地将 C 代码片段编译到我的 Perl 模块?

CTS测试CtsWindowManagerDeviceTestCases模块的testShowWhenLockedImeActivityAndShowSoftInput测试fail项解决方法(代码片段

如何将字符串数据从活动发送到片段?

如何利用redis来进行分布式集群系统的限流设计

jedis连接redis

argparse 代码片段只打印部分日志