rdis-py 2.4.13 documents

来源:互联网 发布:废除 网络中立 知乎 编辑:程序博客网 时间:2024/06/11 08:52

Redis 官方Redis API
StrictRedis Class一直遵从Redis 官方API语法。

  • 例外情况:
    SELECT: 没有实现,请查看Thread Safety 章节的解释
    DEL: ‘del’ 转换为了Python语法,在redis-py 中为 ‘delete’
    CONFIG GET|SET: 分别实现了’config_set’ 和’config_get’
    MULTI/EXEC: 作为Pipeline 类的一部分实现,在调用pipeline方法时指定’use_transaction=True’,当pipeline语句被执行的时候,会使用MULTI和EXEC(将其封装起来)执行pipeline
    SUBSCRIBE/LISTEN: 与pipeline 相似,单独实现了一个PubSub类,在已有基础连接的状态下,不允许执行non-public命令。在redis client
    调用pubsub方法时会返回一个PubSub 实例,使用该实例 可以订阅频道,收听消息。在pipeline和PubSub类都可调用PUBLISH.

Redis Class,是StrictRedis的子类,重写了部分方法命令,可以向后兼容旧版本redids-py

  • 被封装或改造的方法:
    LREM:将’num’和’value’参数逆序,会给 ‘num’提供一个默认值0,
    ZADD: Redis 官方文档指定’score’参数在’value’之前,在Redis 类的参数格式为:name1,score1,name2,score2,… 这种封装的格式转换实现的效率很高,不会影响当前执行状态。
    SETEX: ‘time’和’value’参数逆序
class redis.Redis(host='localhost', port=6379, db=0, password=None, socket_timeout=None, connection_pool=None, charset='utf-8', errors='strict', decode_responses=False, unix_socket_path=None) #Redis类提供对旧版本redis-py 向后兼容,将一些命令参数改变为更加符合python格式,或更加合理。

不同点,具体用法参考StrictRedis类中的实例:

lrem(name, value, num=0)  #将第一个在name列表中 与'value'相同的元素'num'删除  #'num'参数值对操作的影响:  #1.num > 0: 按照从前往后的顺序 ,删除与之相等的元素;  #2.num < 0: 按照从后往前的顺序,删除与之相等的元素;  #3.num = 0: 删除所有与之相等的元素。pipeline(transaction=True, shard_hint=None)  #返回一个新的pipeline对象,将多个命令放在队列中,供以后执行。'transaction'确定是否将所有队列中的命令按照原子性执行。将部分原子性操作分组执行,能够有效的减少clien 与 server的网络交互。setex(name, value, time)  #给与name  相同名称的key 设置 value 为value, 在time时间过后超时,time可用 整型数字表示,也可用python  timedelta objectzadd(name, *args, **kwargs)  #注意 :参数顺序与Redis 官方ZADD的不同,为保持向后兼容,该方法接收参数格式为:name1,score1,name2,score2;但是官方Redis文档希望是:scroe1,name1,socre2,name2.  #如果你想使用标准语法,可以考虑使用StrictRedis 类。  #给与name 相同名称的key设置多对(element-name,score)的值,有两种设置方式:    #作为数组或列表,*args, 格式如下:name1,score1,name2,score2,    #作为字典,**kwargs,格式如下:name1=score1,name2=score2...    #下面的例子会添加4对值给名称为 'my-key'的key:    redis.zadd(‘my-key’, ‘name1’, 1.1, ‘name2’, 2.2, name3=3.3, name4=4.4)

StrictRedis类是Redis 协议的实现,提供了所有的Redis 命令的python接口;
主要使用Connection 和Pipeline 来驱动,实现了在Redis client和Redis server之间一个命令怎样发送和接收的。

class redis.StrictRedis(host='localhost', port=6379, db=0, password=None, socket_timeout=None, connection_pool=None, charset='utf-8', errors='strict', decode_responses=False, unix_socket_path=None)#redis.StrictRedis(...)的方法与redis.Redis(...)是一致的,区别就是上述不同点。详细命令列表请参考https://kushal.fedorapeople.org/redis-py/html/api.html#redis.StrictRedis       """Normal Key-Values Operation:"""  append(key, value)    #为该key追加string 类型value,如果 value不存在则创建,然后返回新的value长度    >>> r.append('test','test is ok')    10L  debug_object(key)    #返回关于该key的特定元信息的版本    >>> r.debug_object('lb')    {'encoding': 'embstr', 'refcount': 1, 'lru_seconds_idle': 289, 'lru': 2267149, 'at': '00007FEC3B00A820', 'serializedlength': 19, 'type': 'Value'}  decr(name, amount=1)    #对名称为name的key值做amunt次递减,如果key 不存在,amount 值会初始化为0    >>> r.getset('integer',128)    >>> r.decr('integer',amount=2)    126  delete(*names)    #删除一个或多个name指定的key    >>> r.delete('lb')    1  exists(name)    #判断key是否存在,然后返回一个布尔值    >>> r.exists('lb')    False    >>> r.exists('integer')    True  expire(name, time)    #给名称为name的key 设置一个超时,time可以是整型,也可以是python 的datetime对象    >>> r.expire('integer',60)    True  get(name)    #返回名称为name的key 的值,如果key不存在,返回None    >>> r.get('test')    'test is ok'    incr(name, amount=1)    #对名称为name的key的值递增amount次,如果key不存在,value则会初始化为amount    >>> r.getset('bg',234)    >>> r.incr('bg',amount=10)    244    >>> r.incr('bh',amount=9)    9        ttl(name)    #当name处于超时阻塞的时候返回已耗用的秒数    r.ttl('q')  type(name)    #返回key的类型    >>> r.type('q')    'set'    >>> r.type('tha')    'hash'  set(name, value)    #设置key name 的值为value    >>> r.set('fu','ck')    True  setex(name, time, value)    #在time 时间内将value 设置为key name,time可以是整型,或python datetime    >>> r.setex('qwe',3,1223456)    True  setnx(name, value)    #如果key name不存在的话,将value设置为key name的value    >>> r.setnx('qwe',1223456)    True  persist(name)    #删除name的 expiration    >>> r.persist('tha')    False  rename(src, dst)    #将key name 由src rename为dst    >>> r.rename('lss','llss')    True  renamenx(src, dst)    #如果dst 不存在,则将key name 由src rename 为 dst    >>> r.renamenx('llss','lss')    True"""List Value Operation:"""  lpush(name, *values)    #将value 压入到名称为name的list的头部    >>> r.lpush('lp',1,2,3,4)    4L    >>> r.lpush('lps',(1,2,3,4))    1L  lpop(name)    #删除并返回该名称为name的list的第一个元素    >>> r.lpop('lp')    '4'    >>> r.lpop('lps')    '(1, 2, 3, 4)'  blpop(keys, timeout=0)    #从名称为name的key的第一个非空列表LPOP一个值    #如果该key 没有一个列表支持LPOP值,则会timeout制定的时间内阻塞,或者有值被push到其中一个list中,    #如果timeout值为0,则会无限期阻塞。    >>> r.blpop('lp')    ('lp', '3')  brpoplpush(src, dst, timeout=0)    #从src的尾部pop一个value,并将其push到dst的头部,然后返回该值    #该命令会在其中任何一个条件先出现的情况时发生阻塞,src没有一个value,timeout超时;timeout 为0 会一直阻塞.    >>> r.brpoplpush('lp','lpdest',timeout=1)    '1'  lpushx(name, value)    #如果list name 存在,则会将讲value 压入到list头部    >>> r.lpush('lss',1,2,3,3,4,45)    6L   lset(name, index, value)    #设置list name在index下标的值为value       >>> r.lset('lss',2,45)    True  lindex(name, index)    #返回list name在Index位置的条目    #支持负数下表如-1,将从list尾部返回第一个条目    >>> r.lindex('lss',2)    '45'  linsert(name, where, refvalue, value)    #将value插入到list name中,是否立即返回取决于插入位置在refvalue 前面或后面,    #如果成功插入返回list的长度,如果refvalue 不存在插入失败返回-1.    '''参数:     name: redis的name     where: BEFORE(前)或AFTER(后)     refvalue: 列表内的值     value: 要插入的数据'''    >>> r.linsert('lss','BEFORE',45,999)    7  llen(name)    #返回list name 的长度    >>> r.llen('lss')    7  rpop(name)    #删除list的最后一个条目,并返回该条目    >>> r.rpop('lss')    '1'  rpoplpush(src, dst)    #RPOP src list 的一个值,并自动将该值LPUSH到dst list,然后返回该值    >>> r.rpoplpush('lss','newl')    '2'  rpush(name, *values)    #将value 压入到list name 的尾部    >>> r.rpush('lss',909,808,707)    8L  rpushx(name, value)    #如果该list 存在,则将value压入到list 尾部。    >>> r.rpushx('lss',707)    9    >>> r.rpushx('lss',77777)    10  lrange(name, start, end)    #返回list name 在下标start,end之间的切片;    start,end可以为负数,与python切片的方法中标记法一致    >>> r.lpush('ss',1,2,2,3,3,4,4,55,6,9)    10L    >>> r.lrange('ss',1,4)    ['6', '55', '4', '4']  lrem(name, count, value)    #删除list name中,第count次出现的与value相等的值    count 在一下情况下的影响如下:    count > 0,从头到尾判断value,从头部移除;    count < 0,从后往前判断value,从尾部移除;    count = 0,删除所有与value 相等的条目。    >>> r.lrem('ss',2,2)    2L  ltrim(name, start, end)    #将list name不在start与end之前的条目删除    start,end可以为负数,与python切片的方法中标记法一致    >>> r.ltrim('ss',1,4)    True  mget(keys, *args)    #将多个key的多个值按照有序列表返回    >>> r.mget('ss','ls')    [None, '[1, 2, 3, 4, 5, 56]']"""Bits Operation:"""  getbit(name, offset)    #判断键name在位移/偏移量offset的value,返回一个布尔值    >>> r.getbit('test',2)    1    >>> r.getbit('test',0)    0    >>> r.getbit('test',3)    1  setbit(name, offset, value)    #在name中标记offset作为一个value,然后判断offset之前的value返回布尔值    #对二进制表示位进行操作    ''' name:redis的name        offset,位的索引(将值对应的ASCII码变换成二进制后再进行索引)        value,值只能是 1 或 0 '''    str="345"    r.set("name",str)    for i in str:        print(i,ord(i),bin(ord(i)))#输出 值、ASCII码中对应的值、对应值转换的二进制    '''    输出:    51 0b110011    52 0b110100    53 0b110101'''    r.setbit("name",6,0)#把第7位改为0,也就是3对应的变成了0b110001    print(r.get("name"))#输出:145"""String Values Operation:"""   getrange(key, start, end)    #返回Key值字符串的子字符串,根据offset的start,end做判断    >>> r.getrange('test',1,3)    'est'  strlen(name)    #返回name的value中存储的byte数    >>> r.getset('str','asdfghjkjdhsgafs')    >>> r.strlen('str')    16  substr(name, start, end=-1)    #返回key name的位于下标start, end 之间的子字符串;start,end为整型。    >>> r.substr('str',3,-5)    'fghjkjdhs'  setrange(name, offset, value)    #从offset开始覆盖name的value的bytes,如果覆盖后的value长度超过原value,则新value则比之前大很多;如果仅是覆盖的部分就比原value 长很多,则不会覆盖,返回新value 的长度。    >>> r.setrange('qwe',12,234567)    18    >>> r.setrange('qwe',7,2345670987654321234567890)    32"""Sets Values Operation:"""  sadd(name, *values)    #将value 添加到set name中    >>> r.sadd('s',9,9,7,6)    3  scard(name)    #返回set name中的元素数量    >>> r.scard('s')    3  sdiff(keys, *args)    #返回指定key值set的不同    >>> r.sadd('q',9,9,7,6)    3    >>> r.sdiff('q','s')    set([])    >>> r.sadd('q',9,9,7,6,3,4,6)    2    >>> r.sdiff('q','s')    set(['3', '4'])  sdiffstore(dest, keys, *args)    #将指定的keys的不同值保存到新的set dest中,并返回dest set的key 的数量    >>> r.sdiffstore('dests','q','s')    2  sinter(keys, *args)    #返回指定keys 的交集    >>> r.sinter('q','s')    set(['9', '7', '6'])  sinterstore(dest, keys, *args)    #将keys 的交集保存在set dest中,然后返回dest中key的数量    >>> r.sinterstore('destq23','q','s')    3  sismember(name, value)    #判定value是不是set name中的成员,返回布尔值。    >>> r.sismember('s',3)    False    >>> r.sismember('s',7)    True  slaveof(host=None, port=None)    #设置Redis server为(host,port)的从属(slave),如果调用参数(host,port)为空则为(master)主数据库实例  smembers(name)    #返回set 的所有成员    >>> r.smembers('q')    set(['9', '3', '4', '7', '6'])  smove(src, dst, value)    #自动将value从src移动到dst       >>> r.smove('q','s',3)    True  spop(name)    #随机删除set name中的值并返回    >>> r.spop('s')    '6'  srandmember(name)    #随机set name返回一个值。    >>> r.srandmember('s')    '9'  srem(name, *values)    #从set name中删除value    >>> r.smembers('s')    set(['9', '3', '7'])    >>> r.srem('s',9,3)    2  sunion(keys, *args)    #返回keys的并集    >>> r.sunion('q','s')    set(['9', '4', '7', '6'])  sunionstore(dest, keys, *args)    #将keys的并集保存到dest,并返回dest的成员数目    >>> r.sunionstore('dest11','q','s')    4  getset(name, value)    #如果key 不存在,将value设置为名称为name的key值,并自动返回value,key name。    >>> r.getset('test','new hello')    'test is ok'    >>> r.getset('haha','new hello')    >>> r.get('haha')    'new hello'  sort(name, start=None, num=None, by=None, get=None, desc=False, alpha=False, store=None)    #将 list 或set排序并返回。    >>> r.sort('q')    ['4', '6', '7', '9']"""Hash Values Operation:"""  hset(name, key, value)    #将key添加到value在 名称为name的hash表中,如果HSET新创建了条目,返回1,否则返回0    >>> r.hset('haa','ha','123')    1L  hdel(name, *keys)    #将名称为name的hash表的keys 删除    >>> r.hdel('haa','ha')  hexists(name, key)    #判断key是否存在于名称为name的hash表中,返回布尔值    >>> r.hexists('haa','ha')    False  hget(name, key)    #返回名称为name的hash表中key 的value    >>> r.hset('haa','we','56')    1L    >>> r.hget('haa','we')    '56'  hgetall(name)    #将hash表的name/value 作为一个python 字典对象返回    >>> r.hgetall('haa')    {'we': '56'}  hincrby(name, key, amount=1)    #对名称为name的hash表的key的value 递增amount次    >>> r.hincrby('haa','we',3)    59L  hkeys(name)    #返回名称为name的hash表的keys,作为list返回    >>> r.hset('haa','wi','96')    1L    >>> r.hkeys('haa')    ['we', 'wi']  hlen(name)    #返回名称为name的hash表的,所有元素的数量    >>> r.hlen('haa')    2  hmget(name, keys, *args)    #返回命令相同键值的列表    >>> r.hmget('haa','wi')    ['96']    >>> r.hmget('haa','wi','we')    ['96', '59']  hmset(name, mapping)         #每个mapping映射字典中的键设置为hash name的值    >>> r.hmset('tha',{'q':1,'w':2})    True    >>> dic={"a1":"aa","b1":"bb"}    >>> r.hmset("mha",dic)    True  hsetnx(name, key, value)    #如果hash表name没有该key,设置key到value,如果HSETNX创建了新条目返回1,否则返回0    >>> r.hsetnx('haa','wi',77)    0L    >>> r.hsetnx('haa','wq',77)    1L  hvals(name)    #返回hash表name中的value列表    >>> r.hvals('mha')    ['aa', 'bb']  mset(mapping)    #设置mapping  字典中每个key为其对应的值     >>> r.mset({'qw':1234,'rt':'good'})    True  msetnx(mapping)    #在任何key都没有被设置的情况下,设置mapping  字典中每个key为其对应的值    >>> r.msetnx({'ss':12,'ww':33})    True"""Zadd Values Operation:"""  zadd(name, *args, **kwargs)    #将多组score,element-name添加到key name中,有以下两种格式:    # As *args,列表形式:score1,name1,score2,name2...    # As **kwargs字典形式:name1=score1,name2=score2...    # 下面的这个例子将会添加四组值到key 'my-key', redis.zadd(‘my-key’, 1.1, ‘name1’, 2.2, ‘name2’, name3=3.3, name4=4.4)    >>> r.zadd('good2','name1',1,'name2',2,)    2    >>> r.zadd('mykey','n1',11,'n3',44,name5=5.5,name6=8.8)    4  zcard(name)    #返回顺序集合中的元素个数    >>> r.zcard('mykey')    4  zincrby(name, value, amount=1)    #对顺序集合 name的value递增amount次    >>> r.zincrby('mykey',10,3)    3.0    >>> r.zincrby('mykey','n1',3)    14.0  zinterstore(dest, keys, aggregate=None)    #将指定的keys顺序集合的元素做交集,然后放到新的集合dest中,在dest中的元素将会根据aggregate参数做aggregate处理,如果aggregate=None,会执行求和。    >>> r.zinterstore('dst3',('good2','mykey'),aggregate='MAX')    0L    >>> r.zinterstore('dst3',('good2','mykey'))    0L  zrange(name, start, end, desc=False, withscores=False, score_cast_func=<type 'float'>)    #返回set name的在start,end下标范围的values,并按升序排序    r.zrange('mykey',1,3,)    ['11', 'name5', 'name6']  zrangebyscore(name, min, max, start=None, num=None, withscores=False, score_cast_func=<type 'float'>)    #返回set name在最大和最小范围内的values    >>> r.zrangebyscore('mykey',0,10000,)    ['10', '11', 'name5', 'name6', 'n1', 'n3']  zrank(name, value)    #判定value是否在set name中的顺序,并将该序返回。    >>> r.zrank('mykey',10)    0    >>> r.zrank('mykey',11)    1  zrem(name, *values)    #从已排序的set name中,删除value    >>> r.zrem('mykey',11)    1  zremrangebyrank(name, min, max)    #删除已排序的set name的所有在min.max序列之间的元素,并将他们返回。    >>> r.zremrangebyrank('meykey',0,10)    0  zremrangebyscore(name, min, max)    #删除已排序的set name的所有在min.max序列之间的score,并将他们返回。    >>> r.zremrangebyscore('mykey',0,20)    4  zrevrange(name, start, num, withscores=False, score_cast_func=<type 'float'>)    #返回已排序的set name中按照描述的排序范围内的值    >>> r.zrevrange('mykey',0,11)    ['n3']  zrevrangebyscore(name, max, min, start=None, num=None, withscores=False, score_cast_func=<type 'float'>)    #返回已排序的set name中按照描述的排序中在最小和最大范围内的值     >>> r.zrevrangebyscore('mykey',-1,100)    []  zrevrank(name, value)    #判断value是否在set name中递减顺序,并返回顺序    >>> r.zadd('mk',n1=1,n2=22,n3=33,n4=44,n5=55,n6=66)    6    >>> r.zrevrank('mk','n2')    4  zscore(name, value)    #返回set name中element-value的score    >>> r.zscore('mk','n4')    44.0  zunionstore(dest, keys, aggregate=None)    #将keys指定的集合做多结构体排序到新的set dest   ,score  将会按照aggregate参数做处理,如过参数为None,则做求和。           >>> r.zunionstore('destz',('mykey','mk'))    6L"""DB Configuration Operation:"""  config_get(pattern='*')    #返回基于pattern 的基本配置的字典    >>> r.config_get(pattern='bind')    {'bind': '127.0.0.1'}    >>> r.config_get(pattern='port')    {'port': '6379'}    >>>  config_set(name, value)    #为名称为name 的元素设置值为value    >>> r.config_set('repl-timeout', '45')    True  dbsize()    #返回当前database 的所有key的数量    >>> r.dbsize()    5L  flushall()    #删除当前主机的所有database的所有key  flushdb()    #删除当前database的所有key    >>> tmps.flushdb()    True  info()    #将Rredis Server 相关信息作为一个字典返回  keys(pattern='*')    #返回与pattern 匹配的key列表    >>> r.keys('b*')    ['bg', 'bh']  lastsave()    #返回Redis Server最后一次保存数据到硬盘的时间    >>> r.lastsave()    datetime.datetime(2017, 5, 22, 16, 42, 31)  set_response_callback(command, callback)    #设置一个自定义的回调响应  shutdown()    #关闭Redis Server    r.shutdown()  save()    #通知Redis Server将数据保存到硬盘,在没有保存完成之前该操作会一直阻塞。    >>> r.save()    True  bgsave()    #告诉Redis Server将其数据保存到硬盘上,与save()方法不同,这个方法是异步执行的,会立刻返回。    >>> r.bgsave()    True  move(name, db)    #将key移动到另一个database db    >>> r.move('ss',db=3)    True  object(infotype, key)    #返回key的 encoding, idletime, or refcount    >>> r.object('refcount','ls')    1    >>> r.object('encoding','ls')    'embstr'    >>> r.object('idletime','ls')    1022  parse_response(connection, command_name, **options)    #解析Redis Server的响应消息  ping()    #ping 检查Redis Server    >>> r.ping()    True  bgrewriteaof()    #告诉Redis Server拿内存数据重写AOF文件    >>> r.bgrewriteaof()    True  echo(value)    #对Redis server输出一个字符串value并返回    >>> r.echo('hello,world')    'hello,world'  randomkey()    #返回 random key的名称    >>> r.randomkey()    'lss'"""Commands Operation:"""  execute_command(*args, **options)    #执行一个命令,并返回解析的结果  transaction(func, *watches, **kwargs)    #可以作为在监控所有在watches指定的keys时,将执行可调用函数作为transaction的便捷方法,传入参数应该是一个Pipeline 对象  unwatch()    #unwatch key值,如果key不存在,则什么都不做    #(Flushes all the previously watched keys for a transaction.    #If you call EXEC or DISCARD, there's no need to manually call UNWATCH.)  watch(*names)   # watch key值,如果key不存在,则什么都不做        (Marks the given keys to be watched for conditional execution of a transaction.)  pipeline(transaction=True, shard_hint=None)    #返回一个新的pipeline对象,支持执行多条语句仅对Redis Server请求一次. 通过减少Redis Client和Server之间back-and-forth TCP会话报文传递,显著的提升一组语句的执行效率。  publish(channel, message)    #在channel发布消息, 返回会收听消息的订阅者数量  pubsub(shard_hint=None)    #返回一个 Publish/Subscribe 对象,在该实例中可以订阅频道,收听发布的消息  lock(name, timeout=None, sleep=0.1)    #使用key 名称name,返回一个与threading.Lock行为 类似的LOCK对象    #如果指定timeout,则会在timeout超时时释放LOCK,默认情况下回一直保持LOCK,直到release()被调用    #当LOCK处于阻塞状态或,其他client持有LOCK状态,则会以sleep为周期检查LOCK状态
Exception:exception redis.AuthenticationErrorexception redis.ConnectionErrorexception redis.DataErrorexception redis.InvalidResponseexception redis.PubSubErrorexception redis.RedisErrorexception redis.ResponseErrorexception redis.WatchError

Response Callbacks

Client 类 使用一个回调集合来讲Redis responses 映射为python type,在Redis client 类中RESPONSE_CALLBACKS定义了一些Callbacks
用户自定义的Callbacks 可以通过 set_response_callback方法添加到每个实例中,该方法接收两个参数,一个是命令名称,一个是Callbacks.使用该方法添加的Callbacks仅在该实例回调的时候有效。如果你想定义或重写一个全局Callbacks,你需要创建一个Redis client类的子类,并将Callback 添加到 REDIS_CALLBACKS的字典中。
Response callbacks 至少需要一个参数:Redis server的response,为了在后续控制如何中断response, Keyword arguments也是可以接收的。这个Keyword arguments 是在command’s call to execute_command期间指定的。 The ZRANGE implementation demonstrates the use of response callback keyword arguments with its “withscores”argument.

Thread Safety

Redis client 实例可以安全的在线程间共享。内部连接实例在命令执行完后是从连接池回收,在命令执行完后直接返回到连接池,命令执行时从不会改变client connection 状态。
然而,需要告诫一下:Redis SELECT命令,SELECT命令允许你在当前连接在使用的情况下切换database,被选择的database会一直保有,直到其他database被选择,或连接被关闭。在连接中创建的事务也会返回到连接其他databases的连接池中。
因此,redis-py没有在client实例中实现SELECT命令。如果你想在一个应用中使用多个redis databases,应该为每一个database创建单独的client instance.
在线程之间透传PubSub对象,和Pipeline对象会不安全。

Pipelines

Pipelines are Redis基础类的子类,支持执行多条语句仅对Redis Server请求一次. 通过减少Redis Client和Server之间back-and-forth TCP会话报文传递,显著的提升一组语句的执行效率。
Pipelines 最简单的例子:

>>> r = redis.Redis(...)>>> r.set('bing', 'baz')>>> # Use the pipeline() method to create a pipeline instance>>> pipe = r.pipeline()>>> # The following SET commands are buffered>>> pipe.set('foo', 'bar')>>> pipe.get('bing')>>> # the EXECUTE call sends all buffered commands to the server, returning>>> # a list of responses, one for each command.>>> pipe.execute()[True, 'baz']

为了使用起来简单,所有的语句会加载到pipeline缓存,返回pipeline对象:

>>> pipe.set('foo', 'bar').sadd('faz', 'baz').incr('auto_number').execute()[True, True, 6]

另外,默认情况下 ,pipeline也可确保缓存里的语句会作为一组原子型语句执行,如果你想禁用piprline的原子属性,但还想将语句放入缓存,则需要关闭transactions。

>>> pipe = r.pipeline(transaction=False)

一个简单事实是,当我们需要原子处理的时候,需要从Redis prior 中回收之前的处理值。举一个实例,让我们假设python没有INCR命令,但我们需要创建一个INCR原子版本。
在python中已经实现 了在本地GET 值,设置值后返回。然而,这个操作不是原子的,因为,多个Client可能会在同一时刻做同样的操作,每个client都会GET到相同的值。
加入WATCH 命令,WATCH提供了能监控一个或多个key 之前状态,去执行处理或传输。如果一些keys在执行该事务时之前发生了变化,那么整体的处理将会取消并且抛出一个 WatchError.我们可以通过以下做法实现

Redis client-side INCR:>>> with r.pipeline() as pipe:...     while 1:...         try:...             # put a WATCH on the key that holds our sequence value...             pipe.watch('OUR-SEQUENCE-KEY')...             # after WATCHing, the pipeline is put into immediate execution...             # mode until we tell it to start buffering commands again...             # this allows us to get the current value of our sequence...             current_value = pipe.get('OUR-SEQUENCE-KEY')...             next_value = int(current_value) + 1...             # now we can put the pipeline back into buffered mode with MULTI...             pipe.multi()...             pipe.set('OUR-SEQUENCE-KEY', next_value)...             # and finally, execute the pipeline (the set command)...             pipe.execute()...             # if a WatchError wasn't raised during execution, everything...             # we just did happened atomically...             break...        except WatchError:...             # another client must have changed 'OUR-SEQUENCE-KEY' between...             # the time we started WATCHing it and the pipeline's execution...             # our best bet is to just retry...             continue

注意:由于Pipeline 在WATCH过程中必须绑定一个Connection,必须注意调用reset()方法使该Connection 在WATCH之后返回到Connection pool。如果Pipeline被用在一个上下文管理器内,如在上面的这个例子,reset()方法会被自动调用。当然你也可以手工显式调用reset()。

>>> pipe = r.pipeline()>>> while 1:...     try:...         pipe.watch('OUR-SEQUENCE-KEY')...         ......         pipe.execute()...         break...     except WatchError:...         continue...     finally:...         pipe.reset()

一个便捷的方法叫做”transaction”可以操控一个WATCH 处理和重试的副本,支持回调,只需要单一参数,一个pipeline对象,被WACHED的一定数量的keys。我们Redis client INCR 命令可以重写为这样,更易读的格式:

>>> 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]
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电脑无法进入路由器设置页面怎么办 笔记本电脑无线网卡坏了怎么办 笔记本内置无线网卡坏了怎么办 笔记本无线网卡坏了怎么办 wif连上不能上网怎么办 手机wifi有个感叹号怎么办 分手不删qq微信怎么办 优盘提示被锁了怎么办 电视无线网卡插上没反应怎么办 光猫没有wan口怎么办 usb无线网卡坏了怎么办 wifi接收器电脑不识别怎么办 无线路由接收器识别不了怎么办 小米3一直闪红灯怎么办 手机拨号键删了怎么办 联想笔记本电脑无线网卡坏了怎么办 联想z360内置无线网卡坏怎么办 usb无线网卡驱动安装失败怎么办 无线网被禁用了怎么办 未连接无线通信已关闭怎么办 手机设置路由器打不开了怎么办 手机打不开登录路由器的网址怎么办 按了光猫复位后怎么办 按了猫的复位键怎么办 望远镜的镜片小水雾是怎么办 坚果r1不断重启怎么办 忘记Wi-Fi密码了怎么办 魅蓝手机null锁住了怎么办 红米手机锁屏了怎么办 不记得锁屏密码怎么办 小米手机音量键坏了怎么办 小米6音量键坏了怎么办 小米2s开不开机怎么办 小米4不充电了怎么办 小米2开不开机怎么办 手机开机键开不了机怎么办 三星s4反复重启怎么办 小米5反复重启怎么办 电脑系统奔溃了怎么办 电脑开机后屏幕出现英文怎么办 小米4开不开机了怎么办