Redis是一个基于内存的高效的键值型非关系型数据库,存取效率极高,而且支持多种存储数据结构,使用也非常简单。
Redis的Python库提供两个类Redis
和StrictRedis
来实现Redis的命令操作。StrictRedis
实现了绝大部分官方的命令,参数也一一对应,比如set()
方法就对应Redis命令的set
方法。而Redis
是StrictRedis
的子类,它的主要功能是用于向后兼容旧版本库里的几个方法。为了做兼容,它将方法做了改写,比如lrem()
方法就将value
和num
参数的位置互换,这和Redis命令行的命令参数不一致。
官方推荐使用StrictRedis
,如果已在本地安装并运行Reids
服务端,可采用如下方式连接:
from redis import StrictRedis
redis = StrictRedis(host='localhost', port=6379, db=0, password='password')
redis.set('name', 'wcjb')
print(redis.get('name'))
输出如下:
b'wcjb'
Redis使用之前需要建立连接,建立断开连接需要消耗大量的时间。使用连接池ConnectionPool
可以实现在客户端建立多个连接,需要的时候从连接池拿过来,用完了再放回去,这样就节省了建立、断开连接所消耗的时间。更进一步来说,由于Redis基于Client-Server模式,因此如果需要使用必须建立连接,C/S模式本身就是一种远程通信的交互模式,因此Redis服务器可以单独作为一个数据库服务器来独立存在。假设Redis服务器与客户端分处在异地,虽然基于内存的Redis数据库有着超高的性能,但是底层的网络通信却占用了一次数据请求的大量时间,因为每次数据交互都需要先建立连接,假设一次数据交互总共用时30ms,超高性能的Redis数据库处理数据所花的时间可能不到1ms,也即是说前期的连接占用了29ms,连接池则可以实现在客户端建立多个链接并且不释放,当需要使用连接的时候通过一定的算法获取已经建立的连接,使用完了以后则还给连接池,这就免去了数据库连接所占用的时间。
from redis import StrictRedis, ConnectionPool
pool = ConnectionPool(host='localhost', port=6379, db=0, password='foobared')
redis = StrictRedis(connection_pool=pool)
下面是结合网上的一些博客总结的使用Redis操作Python的常用键操作,以备查阅使用。
string
Python 操作 Redis 的 redis 模块对字符串(string)的主要操作函数包括:SET、GET、GETSET、SETEX、SETNX、MSET、MSETNX、INCR(INCRBY,DECR,DECRBY 在 python 中庸同一个函数 incr 实现)、APPEND、SETRANGE、STRLEN。函数说明如下:
- SET: 为指定的键(key)设置值(value), set(self, name, value, **kwargs)。
- GET:获取指定键(key)绑定的值(value),get(self, name)。
- GETSET:为指定的键(key)设置新的值(value),并返回旧的值(old Value),getset(self, name, value)
- SETEX:为指定的键(key)设置过期以秒(second)计的过期时间,setex(self, name, value, time)
- SETNX:键(key)不存在时,为键(key)指定值(value),setnx(self, name, value)
- MSET:一次性设置多个键 - 值 (key-value) 对, 函数设置的键 - 值对(即 mapping 所指内容)数据要以 Python 字典数据类型传入,mset(self, mapping)
- MSETNX:键 - 值 (key-value) 对不存在时,设置键 - 值(key-value)对, msetnx(self, mapping),mapping 值参考 6
- INCR:自增函数,默认步长为 1,通过对步长(amount)大小以及字符的控制实现了 INCRBY(amount>=1)、DECR(amount=-1)、DECRBY(amount<=-1)等函数功能,incr(self, name, amount=1)
- APPEND:为指定的字符串追加值,若不存在则直接创建,append(self, key, value)
- SETRANGE:用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始,setrange(self, name, offset, value)
- STRLEN:返回字符串的长度,当 name 不存在时返回 0,strlen(self, name)
示例代码如下:
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
r = redis.Redis(connection_pool=pool)
r.flushall()
r.setex('name', value='liaogx', time=2)
r.mset(k1 = 'v1', k2 = 'v2', k3 = 'v3')
print(r.mget('k1', 'k2', 'k3', 'k4'))
print(r.getset('name', 'liaogaoxiang'))
print(r.getrange('name', 0, 1))
r.setrange('name', 0, 'LIAO')
i = 0
while i < 4:
print(r.get('name'))
time.sleep(1)
i += 1
source = 'foo'
r.set('n1', source)
r.setbit('n1', 7, 1)
'''
注:如果在Redis中有一个对应: n1 = "foo",
那么字符串foo的二进制表示为:01100110 01101111 01101111
所以,如果执行 setbit('n1', 7, 1),则就会将第7位设置为1,
那么最终二进制则变成 01100111 01101111 01101111,即:"goo"
'''
print(r.get('n1'))
print(r.getbit('n1', 7))
r.set('n2', '廖高祥')
print(r.strlen('n2'))
r.set('num', 1)
r.incr('num', amount=10)
r.decr('num', amount=1)
print(r.get('num'))
r.append('num', 111)
print(r.get('num'))
输出结果如下:
[b'v1', b'v2', b'v3', None]
b'liaogx'
b'li'
b'LIAOgaoxiang'
b'LIAOgaoxiang'
b'LIAOgaoxiang'
b'LIAOgaoxiang'
b'goo'
b'10'
b'10111'
list
Python 操作 Redis 主要利用了 redis 模块来实现,list 表操作函数主要模拟了 Redis 操作命令 LPUSH,LRANGE,LINDEX,BLPOP,BRPOP。函数说明如下:
-
lpush 函数实现了从向指定 redis 列表头部压入数据功能,
lpush key value
-
lrange 获取列表指定范围的函数,
lrange key start end
-
lindex 根据列表下标量获取列表元素值,
lindex key index
- blpop 从列表头部取出第一个元素,返回该元素值并从列表删除(l 代表 left,左边)
- brpop 从列表尾部取出第一个元素,返回该元素值并从列表删除(l 代表 right,右边)
- LPUSHX、RPUSHX 以及其他一些 Redis 列表(List)函数目前版本无法实现,如有可实现方法博客代码事例将会得到更新。
示例代码如下:
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
r = redis.Redis(connection_pool=pool)
r.flushall()
r.lpush('oo', 11)
r.lpushx('oo', 00)
print(r.llen('oo'))
r.linsert('oo', 'before', 11, 99)
r.lset('oo', 1, 88)
print(r.lrange('oo', 0, -1))
r.lrem('oo', 88, num=1)
print(r.lrange('oo', 0, -1))
print(r.lpop('oo'))
print(r.lindex('oo', 0))
r.lpush('l1', 11)
r.rpush('l1', 22)
r.rpush('l1', 33)
r.rpush('l1', 44)
r.rpush('l1', 55)
r.ltrim('l1', 1, 3)
print(r.lrange('l1', 0, -1))
r.rpoplpush('l1', 'l1')
print(r.lrange('l1', 0, -1))
r.brpoplpush('l1', 'l1', timeout=3)
print(r.lrange('l1', 0, -1))
print(r.blpop('l1', 3))
print(r.lrange('l1', 0, -1))
'''
# 由于redis类库中没有提供对列表元素的增量迭代,如果想要循环name对应的列表的所有元素,那么就需要:
# 1、获取name对应的所有列表
# 2、循环列表
# 但是,如果列表非常大,那么就有可能在第一步时就将程序的内容撑爆,所有有必要自定义一个增量迭代的功能:
'''
print('自定义增量迭代:')
r.flushall()
r.lpush('l1', 11)
r.rpush('l1', 22)
r.rpush('l1', 33)
r.rpush('l1', 44)
r.rpush('l1', 55)
def list_iter(name):
list_count = r.llen(name)
for index in range(list_count):
yield r.lindex(name, index)
for item in list_iter('l1'):
print(item)
输出结果如下:
[b'0', b'88', b'11']
[b'0', b'11']
b'0'
b'11'
[b'22', b'33', b'44']
[b'44', b'22', b'33']
[b'33', b'44', b'22']
(b'l1', b'33')
[b'44', b'22']
自定义增量迭代:
b'11'
b'22'
b'33'
b'44'
b'55'
sets
Redis 数据库集合对象 (set object) 是由 string 类型的无重复元素的无需集合,底层编码可以是 intset 或者 hashtable。intset 编码的集合对象用整数集合最为底层实现,所有对象元素保存在整数集合中。Python 的 redis 模块实现了 SADD、SCARD 、SDIFF 、SDIFFSTORE、SINTER 、SINTERSTORE、SISMEMBER 、SMEMBERS 、SMOVE、SPOP、SRANDMEMBER、SREM、SUNION、SUNIONSTORE 操作命令的基本用法。函数说明如下:
- SADD:向集合对象添加成员,sadd(self, name, value)
- SCARD:获取集合元素个数,scard(self, name)
- SDIFF:返回给定多个集合对象的差集 (set key1-set key2..-set keyn),从左到右计算集合差集,sdiff(self, keys, *args)
- SDIFFSTORE:返回给定给定多个集合对象的差集并存储在目标(dest)集合中,sdiffstore(self, dest, keys, *args)
- SINTER:返回给定所有集合(keys, args)的交集, sinter(self, keys, args)
- SINTERSTORE:返回给定所有集合(keys, args)的交集并存储在 集合 (dest) 中, sinterstore(self, dest, keys, args)
- SISMEMBER:判断 value 元素是否是集合 name 的成员, 返回布尔逻辑值 True 或者 False,sismember(self, name, value)
- SMEMBERS:返回集合中所元素值的 Python 集合类型数据,smembers(self, name)
- SMOVE:将元素 value 从集合 src 移动到 集合 dest。若元素 value 在集合 src 中不存在,则集合 dest 中不会添加元素 value, smove(self, src, dest, value)
- SPOP:移除并返回集合中的一个随机元素, spop(self, name)
- SRANDMEMBER:返回集合中一个随机数,但是不做移除操作, srandmember(self, name)。从 Redis 2.6 版本开始, 在命令行下 Srandmember 命令接受可选返回元素数量的参数 redis>SRANDMEMBER name count
- SREM:移除集合中一个元素,srem(self, name, value),redis 模块任然沿用 Redis 2.4 版本以前的只接受单个元素的用法。
- SUNION:返回所有给定集合的并集中所有元素,sunion(self, keys, *args)
- SUNIONSTORE:所有给定集合的并集存储在集合 dest 中, sunionstore(self, dest, keys, *args)
- SSCAN:迭代集合中的元素,sscan(self, name, cursor=0, match=None, count=None)
示例代码如下:
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
r = redis.Redis(connection_pool=pool)
r.flushall()
r.sadd('s1', 'v1', 'v1', 'v2', 'v3')
r.sadd('s2', 'v2', 'v4')
print(r.scard('s1'))
print(r.sdiff('s1', 's2'))
r.sdiffstore('s3', 's1', 's2')
print(r.smembers('s3'))
print(r.sinter('s1', 's2'))
r.sinterstore('s4', 's1', 's2')
print(r.smembers('s4'))
print(r.sunion('s1', 's2'))
r.sunionstore('s5', 's1', 's2')
print(r.smembers('s5'))
print(r.sismember('s4', 'v4'))
r.smove('s2', 's1', 'v4')
print(r.smembers('s1'))
r.srem('s1', 'v1')
print(r.spop('s1'))
print(r.srandmember('s1'))
输出结果如下:
{b'v3', b'v1'}
{b'v3', b'v1'}
{b'v2'}
{b'v2'}
{b'v3', b'v2', b'v4', b'v1'}
{b'v3', b'v2', b'v4', b'v1'}
False
{b'v3', b'v2', b'v4', b'v1'}
b'v2'
b'v3'
sorted set
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
命令 | 描述 |
---|---|
Redis Zadd 命令 | 向有序集合添加一个或多个成员,或者更新已存在成员的分数 |
Redis Zcard 命令 | 获取有序集合的成员数 |
Redis Zcount 命令 | 计算在有序集合中指定区间分数的成员数 |
Redis Zincrby 命令 | 有序集合中对指定成员的分数加上增量 increment |
Redis Zinterstore 命令 | 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中 |
Redis Zlexcount 命令 | 在有序集合中计算指定字典区间内成员数量 |
Redis Zrange 命令 | 通过索引区间返回有序集合成指定区间内的成员 |
Redis Zrangebylex 命令 | 通过字典区间返回有序集合的成员 |
Redis Zrangebyscore 命令 | 通过分数返回有序集合指定区间内的成员 |
Redis Zrank 命令 | 返回有序集合中指定成员的索引 |
Redis Zrem 命令 | 移除有序集合中的一个或多个成员 |
Redis Zremrangebylex 命令 | 移除有序集合中给定的字典区间的所有成员 |
Redis Zremrangebyrank 命令 | 移除有序集合中给定的排名区间的所有成员 |
Redis Zremrangebyscore 命令 | 移除有序集合中给定的分数区间的所有成员 |
Redis Zrevrange 命令 | 返回有序集中指定区间内的成员,通过索引,分数从高到底 |
Redis Zrevrangebyscore 命令 | 返回有序集中指定分数区间内的成员,分数从高到低排序 |
Redis Zrevrank 命令 | 返回有序集合中指定成员的排名,有序集成员按分数值递减 (从大到小) 排序 |
Redis Zscore 命令 | 返回有序集中,成员的分数值 |
Redis Zunionstore 命令 | 计算给定的一个或多个有序集的并集,并存储在新的 key 中 |
Redis Zscan 命令 | 迭代有序集合中的元素(包括元素成员和元素分值) |
示例代码如下:
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
r = redis.Redis(connection_pool=pool)
r.flushall()
r.zadd('z1', '11', 1, '22', 2, '33', 3, '44', 4, '55', 5, '66', 6, '66', 7)
print(r.zcard('z1'))
print(r.zcount('z1', 1, 2))
r.zincrby('z1', '11', amount=5)
print(r.zrange('z1', 0, -1, desc=False, withscores=True))
print(r.zrank('z1', 33))
r.zrem('z1', '66')
print(r.zrange('z1', 0, -1, desc=False, withscores=True))
r.zremrangebyrank('z1', 0, 1)
print(r.zrange('z1', 0, -1, desc=False, withscores=True))
r.zremrangebyscore('z1', 4.5, 5.5)
print(r.zrange('z1', 0, -1, desc=False, withscores=True))
print(r.zscore('z1', 11))
r.zadd("zset_name", "a1", 6, "a2", 2, "a3", 5)
r.zadd('zset_name1', a1=7, b1=10, b2=5)
'''
获取两个有序集合的交集并放入dest集合,如果遇到相同值不同分数,则按照aggregate进行操作
aggregate的值为: SUM MIN MAX
'''
r.zinterstore('zset_name2', ('zset_name', 'zset_name1'), aggregate='Sum')
print(r.zrange('zset_name2', 0, -1, desc=False, withscores=True))
输出结果如下:
[(b'22', 2.0), (b'33', 3.0), (b'44', 4.0), (b'55', 5.0), (b'11', 6.0), (b'66', 6.0)]
[(b'22', 2.0), (b'33', 3.0), (b'44', 4.0), (b'55', 5.0), (b'11', 6.0)]
[(b'44', 4.0), (b'55', 5.0), (b'11', 6.0)]
[(b'44', 4.0), (b'11', 6.0)]
6.0
[(b'a1', 13.0)]
hash
Redis 数据库 hash 数据类型是一个 string 类型的 key 和 value 的映射表,适用于存储对象。redis 中每个 hash 可以存储键值对多达 40 亿。Python 的 redis 模块实现了 Redis 哈希(Hash)命令行操作的几乎全部命令,包括 HDEL、HEXISTS、HGET、HGETALL、HINCRBY、HKEYS、HLEN 、HMGET 、HMSET 、HSET 、HSETNX 、HVALS 、HINCRBYFLOAT 等命令。函数说明如下:
- HDEL:删除对应哈希(Hash)表的指定键(key)的字段,hdel(self, name, key)
- HEXISTS:检测哈希(Hash)表对应键(key)字段是否存在,返回布尔逻辑,hexists(self, name, key)
- HGET:获取哈希(Hash)指定键(key)对应的值,hget(self, name, key)
- HGETALL:获取哈希 (Hash) 表的键 - 值对(key-value pairs), 返回 python 字典类型数据,hgetall(self, name)
- HINCRBY:为哈希表(Hash)指定键(key)对应的值(key)加上指定的整数数值(int,可为负值)hincrby(self>, name, key, amount=1),Redis 中本操作的值被限制在 64 位 (bit) 有符号数字。
- HKEYS:返回哈希表(Hash)对应键(key)的数组(Python 称之为列表 List),hkeys(self, name)
- HLEN: 获取哈希表(Hash)中键 - 值对(key-value pairs)个数,hlen(self, name)
- HMGET:获取哈希表(Hash)中一个或多个给点字段的值,不存在返回 nil(Redis 命令行)/None(Python),hmget(self, name, keys),其中 keys 可以为列表(list)
- HMSET:设置对个键 - 值对(key-value pairs)到哈希表(Hash)中,python 输入值(mapping)为字典(dictionary)类型,hmset(self, name, mapping)
- HSET:为哈希表(Hash)赋值,若键(key)存在值(value)则覆盖,不存在则创建,hset(self, name, key, value)
- HSETNX:为哈希表(Hash)不存值(value)的键(key)赋值,存在操作无效,对应值(value)无变化,hsetnx(self, name, key, value)
- HVALS:返回哈希表(Hash)对应值(value)的列表,hvals(self, name)
- HINCRBYFLOAT:为哈希表 key 中的指定字段的浮点数值加上增量 increment ,hincrbyfloat(self, name, key, amount=1.0)
示例代码如下:
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
r = redis.Redis(connection_pool=pool)
r.flushall()
r.hset('n1', 'k1', 'v1')
print(r.hget('n1', 'k1'))
r.hmset('n2', {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'})
print(r.hmget('n2', 'k2'))
print(r.hgetall('n2'))
print(r.hlen('n2'))
print(r.hkeys('n2'))
print(r.hvals('n2'))
print(r.hexists('n2', 'k4'))
r.hdel('n2', 'k3')
r.hset('n3', 'k1', 1)
r.hincrby('n3', 'k1', amount=1)
print(r.hgetall('n3'))
输出结果如下:
b'v1'
[b'v2']
{b'k1': b'v1', b'k2': b'v2', b'k3': b'v3'}
[b'k1', b'k2', b'k3']
[b'v1', b'v2', b'v3']
False
{b'k1': b'2'}
更多命令可以参考 Redis 中文网
网友评论