Redis
python操作Redis,还包括Memcache,RabbitMQ
Redis内容还是比较多的,详细的可以去上面几篇博客
下面我主要挑一些常用的进行总结
Redis和Memcache差不多,也是内存级别的key-value存储系统,不过相比Memcache,Redis支持value类型更多,有5种:
- string(字符串)
- list(链表)
- set(集合)
- zset(有序集合)
- hash(哈希类型,你就理解成我们常用的字典)
而且Redis还支持原子性操作和持久化
安装
- pip install redis
连接
import redis r = redis.Redis(host='10.211.55.4', port=6379) r.set('foo', 'Bar') print r.get('foo') #连接池连接方式,可减少连接花销, 推荐 import redis pool = redis.ConnectionPool(host='10.211.55.4', port=6379) r = redis.Redis(connection_pool=pool) r.set('foo', 'Bar') print r.get('foo')
常规操作
- keys(pattern) 获取所有的键,默认所有
conn.keys()
- scan_iter(pattern) 分批次取出键,减小redis压力
conn.scan_iter("luffy_shopping_car_1*") conn.scan_iter()
- flushall() 清空redis缓存
conn.flushall()
- delete(name) 删除指定key-val,批量删除可传入*list
conn.delete('k1')
- exists(name)
检测redis的name是否存在
- expire(name ,time)
为某个redis的某个name设置超时时间
5大类型
String字符串
- set(name, value, ex=None, px=None, nx=False, xx=False)
在Redis中设置值,默认,不存在则创建,存在则修改 参数: ex,过期时间(秒) 效果等同setex(name, value, time) px,过期时间(毫秒) nx,如果设置为True,则只有name不存在时,当前set操作才执行,效果等同setnx(name, value) xx,如果设置为True,则只有name存在时,岗前set操作才执行
- mset(*args, **kwargs) 批量设置
conn.mset({'k100':'v100', 'k200':'v200'})
- get(name) 获取值
- mget(keys, *args) 批量获取
print(conn.mget('k100', 'k200')) print(conn.mget(['k100','k200']))
- getset(name, value)
设置新值并获取原来的值
- getrange(key, start, end) 切片取value
- setrange(name, offset, value) 指定位置开始进行替换值
- strlen(name) 获取value字节长度,一个汉字是三个字节
- append(key, value) 对value末尾进行拼接值
conn.append('k100', '00000000000000')
- incr(self, name, amount=1)
自增 name对应的值,当name不存在时,则创建name=amount,否则,则自增
- incrbyfloat(self, name, amount=1.0)
- decr(self, name, amount=1)
conn.set('number', 0) conn.incr('number') conn.incr('number') conn.incr('number') #3
Hash字典
- hset(name, key, value)
name对应的hash中设置一个键值对(不存在,则创建;否则,修改)
hsetnx(name, key, value) name下不存在此key,才添加
- hmset(name, mapping) 批量添加
conn.hmset('xx', {'k1':'k1', 'k2':'k2'})
- hget(name,key)
在name对应的hash中获取根据key获取value
- hmget(name, keys, *args) 批量获取
print(conn.hmget('xx', ['k1', 'k2'])) print(conn.hmget('xx', 'k1', 'k2'))
- hgetall(name)
获取name对应的hash所有键值
hlen(name)
获取name对应的hash中键值对的个数
- hkeys(name)
获取name对应的hash中所有的key的值
- hvals(name)
获取name对应的hash中所有的value的值
- hexists(name, key)
检查name对应的hash是否存在当前传入的key
- hdel(name,*keys)
将name对应的hash中指定key的键值对删除
- hincrby(name, key, amount=1)
自增name对应的hash中的指定key的值,不存在则创建key=amount
- hincrbyfloat(name, key, amount=1.0)
- hscan(name, cursor=0, match=None, count=None) 通过游标分批获取数据
- hscan_iter(name, match=None, count=None)
利用yield封装hscan创建生成器,实现分批去redis中获取数据
# 第一次:cursor1, data1 = r.hscan('xx', cursor=0, match=None, count=None) # 第二次:cursor2, data1 = r.hscan('xx', cursor=cursor1, match=None, count=None) # for item in r.hscan_iter('xx'): # print item
List链表
- lpush(name,values) 左添加 [添加]
- lpushx(name,value) name存在才左添加 [添加]
- rpush(name,values) 右添加 [添加]
- rpushx(name,value) name存在才右添加 [添加]
conn.lpush('xx', 11, 22, 33) conn.lpushx('oo', 11) conn.lpushx('xx', 11)
- linsert(name, where, refvalue, value)) [添加] 指定元素前或后插值,
where,BEFORE或AFTER,
refvalue,标杆值,即:在它前后插入数据,
value,要插入的数据
- 如果列表中有多个同样的标杆值,默认是第一个
conn.linsert('xx', 'BEFORE', '33', '8888')
- llen(name)
name对应的list元素的个数
- lset(name, index, value) 指定索引位置改值 [修改]
- lpop(name) 左移除并获取 [获取]
rpop(name) 右移除并获取 [获取]
- lindex(name, index) 指定索引获取
[获取]
- lrange(name, start, end)
在name对应的列表分片获取数据
[获取]
- r.lrem(name, num, value)
在name对应的list中删除指定值
[删除]
# value,要删除的值 # num, num=0,删除列表中所有的指定值; # num=2,从前到后,删除2个; # num=-2,从后向前,删除2个
- ltrim(name, start, end)
name对应的列表中移除没有在start-end索引之间的值
[删除]
- rpoplpush(src, dst)
# 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边 # 参数: # src,要取数据的列表的name # dst,要添加数据的列表的name
- blpop(keys, timeout) 左取,没有值时阻塞
brpop(keys, timeout) 右取,没有值时阻塞
import redis """ redis = { k1:[1,2,3,43,45] } """ conn = redis.Redis(host='47.94.172.250',port=6379,password='Luffy!4321') # 左插入 # conn.lpush('k1',11) # 右插入 # conn.rpush('k1',33) # 左获取 # val = conn.lpop('k1') # val = conn.blpop('k1',timeout=10) # hang住 # 右获取 # val = conn.rpop('k1') # val = conn.brpop('k1',timeout=10) # hang住 # conn.lpush('k1',*[11,22,33,44,55,66,77,88,99,66,666,2234,345234,234])
由于redis链表类型没有提供scan_iter这么一个方法,而且也要防止列表过大,撑爆内存,我们需要自定义列表的scan_iter方法
def list_iter(key,count=100): index = 0 while True: data_list = conn.lrange('k1', index, index+count-1) if not data_list: return index += count for item in data_list: yield item print(conn.lrange('k1',0,101)) for item in list_iter('k1',count=3): print(item)
set集合
另外两个数据类型,集合和有序集合,这里不多赘述,可文头文章
这两种数据类型主要用于交集,差集,并集运算
- 用于去重
- 有序集合用于排序
管道
默认执行一次命令是redis连接会创建(连接池申请连接)和断开(归还连接池),如果想一次执行多条命令,就可以用pipline,而且是原子性操作
import redis """ redis = { k1:[1,2,3,43,45] } """ conn = redis.Redis(host='47.94.172.250',port=6379,password='Luffy!4321') pipe = conn.pipeline(transaction=True) pipe.multi() pipe.set('k2','123') pipe.hset('k3','n1',666) pipe.lpush('k4','laonanhai') pipe.execute()