Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。它提供了Python,Ruby,Erlang,PHP客户端,使用很方便,Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。从盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。
redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类
import redis
import time
# 普通连接方式
r = redis.Redis(host='localhost', port=6379, db=0)
r.set('name', '张三')
print(r.get('name').decode('utf8'))
# 连接池连接方式
pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
r.set('name1','lisi')
print(r.get('name1').decode('utf8'))
'''
在python中返回的值均是byte类型的,需要decode解码才能转为字符类型,为方便以下给出的结果如无decode均是byte类型
1.String操作
redis中的String在内存中按照一个name对应一个value存储
'''
# set() 默认不存在则创建,存在则修改
r.set('sname1', 'myredis1') # 普通创建
r.setex('sname2', 'myredis2', 5) # 设置过期时间(秒)
print(r.get('sname2').decode('utf8')) # myredis2
time.sleep(5)
print(r.get('sname2').decode('utf8')) # error
# mset() 批量设置
r.mset(sname1='s1', sname2='s2')
print(r.mget('sname1', 'sname2')) # [b's1', b's2']
# getset() 设置新值,打印旧值
print(r.get('sname1')) # myredis1
print(r.getset('sname1', 'hahaha')) # myredis1
print(r.get('sname1')) # hahaha
# getrange() 根据字节获取子序列
r.set('name', 'redis')
print(r.getrange('name',0,3)) # redi
# setrange() 修改字符串内容,从制定位置向后替换,新值太长则追加
r.set('name','redis')
r.setrange('name', 1, 'z')
print(r.get('name')) # rzdis
r.setrange('name', 3, 'zzzzz')
print(r.get('name')) # rzdzzzzz
# strlen() 返回值的字节长度,一个汉字3字节
r.set('name','redis')
print(r.strlen('name')) # 5
r.set('name', '张三')
print(r.strlen('name')) # 6
# incr() 自增
print(r.incr('mount')) # 16
print(r.get('mount')) # 16
# decr() 自减
print(r.decr('mount')) # 15
print(r.get('mount')) # 15
# append() 对值进行追加
r.set('name','redis')
print(r.get('name')) # redis
r.append('name','py')
print(r.get('name')) # redispy
'''
2.Hash操作
redis中的hash在内存中类似于一个name对应一个dict来存储
'''
# hset() 设置一个name对应一个k-v键值对
# hget() 根据name中的key获取value
# hgetall() 获取name中的所有k-v
r.hset('hname','key1','value1')
print(r.hget('hname','key1')) # value1
print(r.hgetall('hname')) # {'key1':'value1'}
# hmset() 批量设置键值对
# hmget() 在name中获取多个key的值
d={'a1':'aa','b1':'bb'}
r.hmset('hname', d)
print(r.hget('hname', 'a1')) # aa
print(r.hmget('hname','a1','b1')) # ['aa', 'bb']
# hlen() 获取hash中键值对个数
# hkeys() 获取所有的key
# hvals() 获取所有的value
d = {'a1':'aa','b1':'bb'}
r.hmset('hname', d)
print(r.hlen('hname')) # 3
print(r.hkeys('hname')) # ['a1','b1','key1']
print(r.hvals('hname')) # ['aa','bb','value1']
# hexists() 判断name对应的hash是否存在传入的key
print(r.hexists('hname', 'a1')) # True
print(r.hexists('hname', 'a2')) # False
# hdel() 删除指定name对应的key所在键值对
r.hdel('hname', 'a1')
print(r.hget('hname', 'a1')) # None
'''
3.List操作
redis中的list在内存中按照一个name对应一个list来存储
'''
# lpush() 在name对应的list中最左添加元素,rpush()为最右添加
# lpushx() 当name存在时才执行最左添加, rpushx()为name存在时最右添加
r.lpush('lname',2)
r.lpush('lname', 4,6)
# llen() name对应的list元素个数
print(r.llen('lname')) # 3
# lrange() 分片获取元素
print(r.lrange('lname',0,5)) # [b'6', b'4', b'2']
# linsert() 在name对应的list中某一个值的前或后插入新值
r.linsert('lname','BEFORE','2','ss')
print(r.lrange('lname',0,-1)) # [b'6', b'4', b'ss', b'2']
# lset() 对list中某一个位置重新赋值
r.lset('lname',1,'gg')
print(r.lrange('lname',0,-1)) # [b'6', b'gg', b'ss', b'2']
# lrem() 移除list中指定的值,默认删除所有指定值
r.lrem('lname', 2)
print(r.lrange('lname',0,-1)) # [b'6', b'gg', b'ss']
# lpop() 移除列表左侧第一个元素,并返回移除元素
print(r.lpop('lname')) # b'6'
# lindex() 根据索引获取列表元素
print(r.lindex('lname', 1)) # b'ss'
# ltrim() 移除列表中没有在改索引之内的值
r.ltrim('lname', 0, 1)
# rpoplpush() 从前一个列表中取出最右元素,同时将其添加到后一个列表的最左边
r.lpush('list1', 1,2)
r.lpush('list2', 3,4)
r.rpoplpush('list1', 'list2')
print(r.lrange('list1', 0, -1)) # [b'2']
print(r.lrange('list2', 0, -1)) # [b'1', b'4', b'3']
# blpop() 将多个列表排列,按照从左到右去移除各个列表内的元素
r.lpush("list_name",3,4,5)
r.lpush("list_name1",3,4,5)
while True:
print(r.blpop(['list_name', 'list_name1'], timeout=0))
print(r.lrange("list_name", 0, -1), r.lrange("list_name1", 0, -1))
# (b'list_name', b'5')
# [b'4', b'3', b'2', b'3'] [b'5', b'4', b'3']
# (b'list_name', b'4')
# [b'3', b'2', b'3'] [b'5', b'4', b'3']
# (b'list_name', b'3')
# [b'2', b'3'] [b'5', b'4', b'3']
# (b'list_name', b'2')
# [b'3'] [b'5', b'4', b'3']
# (b'list_name', b'3')
# [] [b'5', b'4', b'3']
# (b'list_name1', b'5')
# [] [b'4', b'3']
# (b'list_name1', b'4')
# [] [b'3']
# (b'list_name1', b'3')
# [] []
'''
4.Set操作
集合,不含有重复值
'''
# sadd() 给name对应的集合中添加元素
r.sadd('setname', 'aa')
r.sadd('setname', 'aa', 'bb')
# smembers() 获取集合所有成员
print(r.smembers('setname')) # {b'bb', b'aa'}
# scard() 获取集合中的元素个数
print(r.scard('setname')) # 2
# sdiff() 差集,在第一个name集合中存在,且不在其他name集合中的,元素集合
r.sadd('setname1','a','b','c')
r.sadd('setname2', 'a','b','cc')
print(r.sdiff('setname1', 'setname2')) # {b'c'}
# sinter() 交集,多个name集合的交集
r.sadd('setname1','a','b','c')
r.sadd('setname2', 'a','b','cc')
print(r.sinter('setname1','setname2')) # {b'a', b'b'}
# sunion() 并集,多个集合的并集
print(r.sunion('setname','setname1', 'setname2')) # {b'c', b'bb', b'aa', b'b', b'cc', b'a'}
# sismember() 检查value是否在集合中
print(r.sismember('setname1', 'b')) # True
# smove() 将元素从一个集合移动到另一个集合
print(r.smembers('setname1')) # {b'b', b'a', b'c'}
r.smove('setname1','setname2', 'c')
print(r.smembers('setname1')) # {b'b', b'a'}
# spop(name) 从集合最右侧移除一个元素并返回
srem(name, values) 从集合中删除某些值
srandmember(name, numbers) 从集合中随机获取numbers个元素
print(r.srandmember('setname2', 2)) # [b'b', b'cc']
'''
5.有序集合
在集合的基础上,根据元素分数,为元素排序
'''
# zadd() 有序集合添加元素
r.zadd('zsetname', 'a', 5, 'b', 1)
r.zadd('zsetname1', a=5, b=1, c=3)
# zcard(name) 获取有序集合中元素数量
print(r.zcard('zsetname')) # 2
# zcount(name, min, max) 获取有序集合中分数在[min, max]中的个数
print(r.zcount('zsetname1', 1, 3)) # 2
# zincrby(name, value, amount) 自增有序集合内value对应的分数
r.zincrby('zsetname','b', amount=2)
# zrange() 按照索引获取有序集合内的元素, 默认按照分数升序排列
print(r.zrange('zsetname', 0, -1, desc=False, withscores=True)) # [(b'b', 3.0), (b'a', 5.0)]
# zrank(name, value) 获取value在name中的索引位置
print(r.zrank('zsetname', 'a')) # 1
# zscore(name, value) 获取value在name中的分数
print(r.zscore('zsetname', 'a')) # 5.0
# zrem(name, values) 从有序集合中移除某些值
r.zrem('zsetname', 'a', 'b')
print(r.zrange('zsetname', 0, -1)) # []
'''
6.其他操作
'''
# delete(*names) 根据name删除redis中任意类型
# exists(name) 检测redis的name是否存在
# keys(pattern='*') 根据通配符获取redis的name列表
# print(r.keys(pattern='*')) # [b'setName', b'name', b'sn2']
# expire(name, time) 为某个name设置过期时间
# rename(src, dst) 重命名
# move(name, db) 将redis的某个值移动到指定的db下
# randomkey() 随机获取redis的name
# type(name) 获取name对应的类型
'''
7.管道
redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,
如果想在一次请求中执行多个命令,可以使用pipline管道实现,默认情况下一次pipline是原子性操作
'''
pipe = r.pipeline(transaction=True)
r.set('name', 'a')
r.set('name', 'b')
pipe.execute()
print(r.get('name')) # b'b'
'''
8.发布和订阅
首先定义一个RedisHelper类,连接redis,定义频道为monitor,定义发布publish和订阅subscribe方法
'''
class RedisHelper:
def __init__(self):
self._conn = redis.Redis(host='localhost', port=6379)
self.channel = 'monitor' # 定义频道名称
def publish(self, msg):
# 定义发布方法
self._conn.publish(self.channel, msg)
return True
def subScribe(self):
# 定义订阅方法
pub = self._conn.pubsub()
pub.subscribe(self.channel)
pub.parse_response()
return pub
# # 发布者 pub.py
# from redistest import RedisHelper
# puber = RedisHelper()
# puber.publish('hello')
#
# # 订阅者 sub.py
# from redistest import RedisHelper
# suber = RedisHelper()
# suber_redis = suber.subScribe()
# while True:
# msg = suber_redis.parse_response()
# print(msg) # [b'message', b'monitor', b'hello']
感谢原作者整理,我个人重新手打一遍。