redis中的String在在内存中按照name:value
来存储的。
# 参数:
# ex,过期时间(秒)
# px,过期时间(毫秒)
# nx,如果设置为True,则只有name不存在时,当前set操作才执行
# xx,如果设置为True,则只有name存在时,岗前set操作才执行
r.set('name', 'redis', ex=60, nx=True)
print(r.get('name'))
# 结果:
# b'redis'
ret = r.getset('name', 'new value')
print(ret)
# b'redis'
print(r.get('name'))
# b'new value'
r.setnx('num', 123)
print(r.get('num'))
# 结果:
# b'123'
# time,过期时间(数字秒 或 timedelta对象)
r.setex('ex', 20, 'guoqi')
print(r.get('ex'))
r.psetex('pex', 20000, 'weimiao')
print(r.get('ex'))
# 结果:
# b'guoqi'
# b'guoqi'
# 20s后 ex、pex消失
tom = {'name': 'Tom', 'age': 20, 'id': 1}
r.mset(tom)
print(f"name:{r.get('name')}\n'age':{r.get('age')}\n'id':{r.get('id')}")
# 结果
# name:b'Tom'
# 'age':b'20'
# 'id':b'1'
r.set('num', '0123456')
ret = r.getrange('num', 1, 4)
print(ret)
# b'1234'
r.setrange('num', 4, 'adcde')
print(r.get('num'))
# b'0123adcde'
r.set('bit', '012345')
# 012345 ascii = 30 31 32 33 34 35
# = 00110000 00110001 00110010 ...
# 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)
r.setbit('bit', 1, 1) # 00110000 -> 01110000=70=p
print(r.get('bit'))
# b'p12345'
print(r.getbit('bit', 2))
# 1
r.set('bit', '1') # 1 = 31 = 00110001
print(r.bitcount('bit', 0, -1))
# 3
# bit 操作 与 或 亦或 非
# dest, 新的Redis的name
# *keys,要查找的Redis的name
r.set('a', 0x11) # 17 = 31 37 = 00110001 00110111
r.set('b', 0x22) # 34 = 33 34 = 00110011 00110100
r.bitop('AND', 'yu', 'a', 'b') # 00110001 00110100 = 31 34 = 14
r.bitop('OR', 'huo', 'a', 'b') # 00110011 00110111 = 33 37 = 37
r.bitop('XOR', 'yihuo', 'a', 'b') # 00000010 00000011 = 02 03
r.bitop('NOT', 'fei', 'a') # 11001110 11001000 = ce c8
print(r.get('yu'))
# b'14'
print(r.get('huo'))
# b'37'
print(r.get('yihuo'))
# b'\x02\x03'
print(r.get('fei'))
# b'\xce\xc8'
r.set('len', '012345678')
ret = r.strlen('len')
print(ret)
# 9
r.set('num', 1)
r.incr('num')
print(r.get('num'))
# b'2'
r.incrby('num', 3)
print(r.get('num'))
# b'5'
r.incrbyfloat('num', 2.1)
print(r.get('num'))
# b'7.1'
# 减
r.set('num', 10)
r.decr('num')
print(r.get('num'))
# b'9'
r.decrby('num', 4)
print(r.get('num'))
# b'5'
# 追加
r.set('code', 'abcdefg')
r.append('code', 'hijk')
print(r.get('code'))
b'abcdefghijk'
Redis hash 是一个string类型的field和value的映射表
,hash特别适合用于存储对象。Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。
r.hset('t1', 'name', 'jack')
print(r.hget('t1', 'name'))
# b'jack'
r.hsetnx('t1', 'name', 'ulysses')
print(r.hget('t1', 'name'))
# b'jack'
d1 = {'name': 'Jack', 'id': 1, 'location': 'US'}
r.hmset('t1', d1)
print(r.hgetall('t1'))
{b'name': b'Jack', b'id': b'1', b'location': b'US'}
keys = ['name', 'location']
print(r.hmget('t1', keys, 'id'))
[b'Jack', b'US', b'1']
d2 = {'date': str(datetime.now().date()), 'name': 'Akali', 'age': '16', 'id': 2}
r.hmset('t2', d2)
print(r.hlen('t2'))
# 4
print(r.hkeys('t2'))
# [b'date', b'name', b'age', b'id']
print(r.hvals('t2'))
# [b'2018-11-25', b'Akali', b'16', b'2']
print(r.hgetall('t1'))
# {b'name': b'Jack', b'id': b'1', b'location': b'US'}
if r.hexists('t1', 'name'):
r.hdel('t1', 'name')
print(r.hgetall('t1'))
# {b'id': b'1', b'location': b'US'}
print(r.hget('t2', 'id'))
# b'2'
if r.hexists('t2', 'id'):
r.hincrby('t2', 'id', 25)
print(r.hget('t2', 'id'))
# b'27'
r.hincrbyfloat('t2', 'id', 3.14)
print(r.hget('t2', 'id'))
# b'30.14'
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
l1 = [0, 1, 2, 3, 4, 5, 6, 7]
r.lpush('l1', *l1)
print(r.lrange('l1', 0, -1))
# [b'7', b'6', b'5', b'4', b'3', b'2', b'1', b'0']
r.lpush('l1', 'a')
r.lpushx('l1', 'b')
ret = r.lpop('l1')
print(ret)
# b'b'
print(r.lrange('l1', 2, 5))
# [b'6', b'5', b'4', b'3']
print(r.lrange('l1', 10, 15))
# []
print(r.lrange('l1', 4, 1))
# []
if r.exists('l2'):
r.delete('l2')
l2 = ['a', 'b', 'c', 'd', 'e']
r.rpush('l2', *l2)
print(r.lrange('l2', 0, -1))
# [b'a', b'b', b'c', b'd', b'e']
r.linsert('l2', 'before', 'b', '0')
r.linsert('l2', 'after', 'd', '1')
print(r.lrange('l2', 0, -1))
# [b'a', b'0', b'b', b'c', b'd', b'1', b'e']
print(r.llen('l2'))
# 7
print(r.lindex('l2', 1))
# b'0'
print(r.lindex('l2', 4))
# b'd'
if r.exists('l3'):
r.delete('l3')
l3 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
r.rpush('l3', *l3)
r.lset('l3', 1, 1)
r.lset('l3', 3, 1)
print(r.lrange('l3', 0, -1))
# [b'a', b'1', b'c', b'1', b'e', b'f', b'g', b'h']
# count > 0: Remove elements equal to value moving from head to tail.
# count < 0: Remove elements equal to value moving from tail to head.
# count = 0: Remove all elements equal to value.
r.lrem('l3', 2, 1)
print(r.lrange('l3', 0, -1))
# [b'a', b'c', b'e', b'f', b'g', b'h']
r.ltrim('l3', 1, 4)
print(r.lrange('l3', 0, -1))
# [b'c', b'e', b'f', b'g']
最后
一个元素,并将该元素添加到另一个列表的头部
并返回:if r.exists('l4'):
r.delete('l4')
if r.exists('l5'):
r.delete('l5')
l4 = ['US', 'CN', 'JP', 'FR', 'UK']
l5 = ['baidu', 'google', 'facebook', 'twitter']
r.rpush('l4', *l4)
r.rpush('l5', *l5)
r.rpoplpush('l4', 'l5')
print(r.lrange('l4', 0, -1))
# [b'US', b'CN', b'JP', b'FR']
print(r.lrange('l5', 0, -1))
# [b'UK', b'baidu', b'google', b'facebook', b'twitter']
阻塞
列表直到等待超时
或发现可弹出元素
为止先运行①
ret1 = r.blpop('l6', timeout=10)
ret2 = r.brpop('l7', timeout=10)
print(ret1)
print(ret2)
再运行②
if r.exists('l6'):
r.delete('l6')
if r.exists('l7'):
r.delete('l7')
l6 = [1, 2, 3, 4, 5, 6]
l7 = ['a', 'b', 'c', 'd']
# ret1 = r.blpop('l6', timeout=10)
# ret2 = r.brpop('l7', timeout=10)
r.rpush('l6', *l6)
r.rpush('l7', *l7)
print(r.lrange('l6', 0, -1))
print(r.lrange('l7', 0, -1))
①的结果:
(b'l6', b'1')
(b'l7', b'd')
②的结果:
[b'2', b'3', b'4', b'5', b'6']
[b'a', b'b', b'c']
Redis 的 Set 是 String 类型的无序
集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
if r.exists('s1'):
r.delete('s1')
r.sadd('s1', *s1)
print(r.scard('s1'))
# 10
if r.sismember('s1', 'US'):
r.srem('s1', 'US')
print(r.smembers('s1'))
# {b'3', b'Tom', b'2', b'b', b'a', b'Jack', b'1', b'CN', b'z'}
s2 = ['baidu', 'google', 'sina', 'sohu', 'twitter']
if r.exists('s2'):
r.delete('s2')
r.sadd('s2', *s2)
ret = r.spop('s2')
print(ret)
# b'sohu'
print(r.smembers('s2'))
# {b'google', b'sina', b'twitter', b'baidu'}
ret = r.srandmember('s2', 3)
print(ret)
# [b'twitter', b'baidu', b'google']
print(r.smembers('s2'))
# {b'google', b'sina', b'twitter', b'baidu'}
差集
交集
并集
s3 = ['baidu', 'google', 'sina', 'sohu', 'twitter', 1, 2, 3, 'a', 'b']
s4 = ['a', 'b', 'c', 1, 2, 'google']
if r.exists('s3'):
r.delete('s3')
if r.exists('s4'):
r.delete('s4')
r.sadd('s3', *s3)
r.sadd('s4', *s4)
diff = r.sdiff('s3', 's4')
r.sdiffstore('s_diff', 's3', 's4')
print(diff)
print(r.smembers('s_diff'))
# {b'3', b'sina', b'sohu', b'baidu', b'twitter'}
inter = r.sinter('s3', 's4')
r.sinterstore('s_inter', 's3', 's4')
print(inter)
print(r.smembers('s_inter'))
# {b'google', b'b', b'2', b'a', b'1'}
union = r.sunion('s3', 's4')
r.sunionstore('s_union', 's3', 's4')
print(union)
print(r.smembers('s_union'))
# {b'3', b'google', b'sina', b'sohu', b'baidu', b'c', b'b', b'twitter', b'2', b'a', b'1'}
r.smove('s3', 's4', 'sina')
print(r.smembers('s3'))
# {b'3', b'google', b'sohu', b'baidu', b'b', b'twitter', b'2', b'a', b'1'}
print(r.smembers('s4'))
# {b'google', b'sina', b'c', b'b', b'2', b'a', b'1'}
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。
if r.exists('zs1'):
r.delete('zs1')
zs = {'us': 1, 'cn': 2, 'jp': 2.5, 'kr': 4, 'eu': 3.5}
r.zadd('zs1', zs)
print(r.zcard('zs1'))
# 5
print(r.zcount('zs1', 2, 4))
# 4
print(r.zscore('zs1', 'jp'))
# 2.5
print(r.zrange('zs1', 0, -1, withscores=True))
# [(b'us', 1.0), (b'cn', 2.0), (b'jp', 2.5), (b'eu', 3.5), (b'kr', 4.0)]
print(r.zrevrange('zs1', 0, -1))
# [b'kr', b'eu', b'jp', b'cn', b'us']
切片
从高到底
if r.exists('zs2'):
r.delete('zs2')
zs2 = {'a': 1, 'b': 2, 'c': 2.5, 'd': 2.2, 'e': 3.5, 'f': 0.5}
r.zadd('zs2', zs2)
r.zincrby('zs2', 2, 'c')
print(r.zscore('zs2', 'c'))
# 4.5
print(r.zlexcount(name="zs2", min="-", max="+"))
# 6
print(r.zrangebylex(name='zs2', min="-", max="+"))
# [b'f', b'a', b'b', b'd', b'e', b'c']
print(r.zrevrangebylex('zs2', "[f", "[a"))
# [b'c', b'e', b'd', b'b', b'a', b'f']
print(r.zrangebyscore('zs2', 0, 4))
# [b'f', b'a', b'b', b'd', b'e']
print(r.zrevrangebyscore('zs2', 5, 1, withscores=True))
# [(b'c', 4.5), (b'e', 3.5), (b'd', 2.2), (b'b', 2.0), (b'a', 1.0)]
if r.exists('zs2'):
r.delete('zs2')
zs3 = {'a': 1, 'b': 2, 'c': 2.5, 'd': 3.2, 'e': 3.5, 'f': 3.55, 'g': 4, 'h': 4.1,
'i': 4.3, 'j': 4.5, 'k': 5, 'l': 5.3, 'm': 5.6, 'n': 5.8, 'o': 6}
r.zadd('zs3', zs3)
print(r.zrank('zs3', 'f'))
# 5
print(r.zrevrank('zs3', 'f'))
# 9
r.zrem('zs3', 'a')
print(r.zrange('zs3', 0, -1, withscores=True))
# [(b'b', 2.0), (b'c', 2.5), (b'd', 3.2), (b'e', 3.5), (b'f', 3.55), (b'g', 4.0), (b'h', 4.1), (b'i', 4.3), (b'j', 4.5), (b'k', 5.0), (b'l', 5.3), (b'm', 5.6), (b'n', 5.8), (b'o', 6.0)]
r.zremrangebylex('zs3', '[b', '[d')
print(r.zrange('zs3', 0, -1, withscores=True))
# [(b'e', 3.5), (b'f', 3.55), (b'g', 4.0), (b'h', 4.1), (b'i', 4.3), (b'j', 4.5), (b'k', 5.0), (b'l', 5.3), (b'm', 5.6), (b'n', 5.8), (b'o', 6.0)]
r.zremrangebyrank('zs3', '2', '4')
print(r.zrange('zs3', 0, -1, withscores=True))
# [(b'e', 3.5), (b'f', 3.55), (b'j', 4.5), (b'k', 5.0), (b'l', 5.3), (b'm', 5.6), (b'n', 5.8), (b'o', 6.0)]
r.zremrangebyscore('zs3', 3, 5)
print(r.zrange('zs3', 0, -1, withscores=True))
# [(b'l', 5.3), (b'm', 5.6), (b'n', 5.8), (b'o', 6.0)]
if r.exists('zs4'):
r.delete('zs4')
if r.exists('zs5'):
r.delete('zs5')
zs4 = {'baidu': 1, 'google': 2, 'sina': 4, 'twitter': 3, 'facebook': 3.54}
zs5 = {'taobao': 1, 'youtube': 2, 'twitch': 4, 'google': 5, 'sina': 5.5}
r.zadd('zs4', zs4)
r.zadd('zs5', zs5)
r.zinterstore('zs_inter', ('zs4', 'zs5'))
r.zunionstore('zs_union', ('zs4', 'zs5'))
print(r.zrange('zs_inter', 0, -1, withscores=True))
# [(b'google', 7.0), (b'sina', 9.5)]
print(r.zrange('zs_union', 0, -1, withscores=True))
# [(b'baidu', 1.0), (b'taobao', 1.0), (b'youtube', 2.0), (b'twitter', 3.0), (b'facebook', 3.54), (b'twitch', 4.0), (b'google', 7.0), (b'sina', 9.5)]
redis-5.0版本新内容
if r.exists('zs6'):
r.delete('zs6')
zs6 = {'a': 1, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5}
r.zadd('zs6', zs6)
print(r.zpopmax('zs6', 2))
# [(b'f', 5.0), (b'e', 4.0)]
print(r.zpopmin('zs6', 2))
# [(b'a', 1.0), (b'b', 1.0)]
print(r.zrange('zs6', 0, -1))
# [b'c', b'd']
Redis 2.8中引入的* SCAN命令使用起来很麻烦。 虽然完全支持这些命令,但redis-py还公开了以下返回Python迭代器的方法:scan_iter,hscan_iter,sscan_iter和zscan_iter。
for key, value in (('A', '1'), ('B', '2'), ('C', '3')):
r.set(key, value)
for key in r.scan_iter():
print(key, r.get(key))
# b'C' b'3'
# b'B' b'2'
# b'A' b'1
s1 = [1, 2, 3, 4, 'white', 'black']
s2 = ['a', 'b', 'c', 'Jack']
r.sadd('s1', *s1)
r.sadd('s2', *s2)
for member in r.sscan_iter('s1'):
print(member)
print('---------')
for member in r.sscan_iter('s2'):
print(member)
# b'2'
# b'3'
# b'black'
# b'4'
# b'white'
# b'1'
# ---------
# b'Jack'
# b'b'
# b'a'
# b'c'
d1 = {'name': 'Jack', 'id': 1, 'location': 'US'}
r.hmset('h1', d1)
for field in r.hscan_iter('h1'):
print(field)
# (b'name', b'Jack')
# (b'id', b'1')
# (b'location', b'US')
zs = {'a1': 1, 'a2': 2, 'a3': 2.5, 'b1': 4, 'b2': 3.5}
r.zadd('zs1', zs)
for field in r.zscan_iter('zs1', match='a*'):
print(field)
(b'a1', 1.0)
(b'a2', 2.0)
(b'a3', 2.5)