基於python操縱redis入門介紹python
by:授客 QQ:1033553122redis
redis-3.0.7數據庫
CentOS 6.5-x86_64安全
python 3.3.2服務器
Redis客戶端實例是線程安全的,能夠直接將Redis鏈接實例設置爲一個全局變量,直接使用。若是須要另外一個Redis實例,就須要從新建立redis鏈接實例來獲取一個新的鏈接
示例
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
import redis
if __name__ == '__main__':
r = redis.StrictRedis(host='192.168.1.103', port=6379, db='0')
result = r.set('name', 'shouke') # 存儲鍵-值
print('result of set: %s' % result)
r.set('hobby', 'music')
name = r.get('name') # 獲取鍵「name」對應的值
print('name: %s' % name)
keys = r.keys() # 獲取全部鍵
print('keys: %s' % keys)
dbsize = r.dbsize() # redis數據庫包的記錄數(key的數量)
print('dbsize: %s' % dbsize)
result = r.delete('hobby') # 根據指定的鍵,刪除指定鍵-值
print('result of delete: %s' % result)
result = r.save() # 執行「檢查點」操做,將數據寫回磁盤。保存時阻塞
print('result of save: %s' % result)
hobby = r.get('hobby')
print('hobby: %s' % hobby)
name = r['name'] # 獲取鍵「name」對應的值
print('name: %s' % name)
result = r.flushdb() # 清空數據當前庫中的全部數據
print('result of flushdb: %s' % result)
print('dbsize: %s' % r.dbsize())
結論:
result of set: True
name: b'shouke'
keys: [b'name', b'hobby']
dbsize: 2
result of delete: 1
result of save: True
hobby: None
name: b'shouke'
result of flushdb: True
dbsize: 0
鏈接池
redis-py使用鏈接池來關聯鏈接到Redis服務器的鏈接。默認的,每一個Redis實例會按順序建立本身的鏈接池。能夠重寫該行爲,以下:
pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
鏈接
鏈接池管理一系列的鏈接實例。redis-py擁有兩種類型的鏈接。默認的,Connection基於普通TCP socket的鏈接,UnixDomainSocketConnection容許運行在相同設備的客戶端做爲服務器,經過一個unix domain socket進行鏈接,使用示例以下:
r = redis.Redis(unix_socket_path='/tmp/redis.sock')
注:確保在redis.conf文件中定義了unixsocket參數(默認的,該參數已被註釋掉)
也能夠建立本身的Connection子類
pool = redis.ConnectionPool(connection_class=YourConnectionClass,
your_arg='...', ...)
解析器Parsers
redis-py有兩種paser類,PythonParser和HiredisParser。默認的,redis-py會試圖使用HiredisParser若是已安裝hiredis模塊,且不然使用PythonParser。使用Hiredis能夠大大提升解析返回結果的速度。
響應回調
客戶端類使用了一系列的回調來轉換Redis響應爲適當的python類型。這類回調函數在Redis客戶端類一個名叫RESPONSE_CALLBACKS的字典中進行了定義了。
使用set_response_call方法能夠爲每一個實例添加客戶端回調。該方法接收兩個參數:命令行名稱和回調。這種方式添加的回調函數僅在被添加的實例有效。若是想定義或重寫全局的回調函數,能夠定一個Redis的子類並添加回調用到REDIS_CALLBACKS字典。
管道(Pipelines)
Redis類的子類,在單一請求中緩衝發往服務器的多條命令。經過減小往返於服務器和客戶端之間TCP包數量,顯著的提升分組命令的執行性能。
示例
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
import redis
if __name__ == '__main__':
pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
result = r.set('name', 'shouke')
print(result)
pipe = r.pipeline() # 建立一個管道實例
result = pipe.set('name2', 'ishouke')
print(result)
result = pipe.get('name2')
print(result)
result = pipe.execute() # 把全部緩衝命令發送到服務器,返回一個列表,包含每一個命令的執行結果
print(result)
運行結果:
True
Pipeline>>
Pipeline>>
[True, b'ishouke']
注:重複運行的狀況下,若是key重複了,redis默認直接覆蓋舊值
也能夠改爲以下方式
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
import redis
if __name__ == '__main__':
pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
pipe = r.pipeline()
name2 = []
result = pipe.set('name', 'shouke').sadd('ishouke', 'name').incr('num').execute()
print(result)
print(r.keys())
運行結果:
[True, 1, 1]
[b'ishouke', b'name', b'num']
incr指定的鍵不能和sadd,set中指定的鍵相同,不然可能報錯,相似以下:
redis.exceptions.ResponseError: Command # 3 (INCRBY name2 1) of pipeline caused error: WRONGTYPE Operation against a key holding the wrong kind of value
默認的狀況下,管道中緩衝的指命令組爲一個原子操做,執行
pipe = r.pipeline(transaction=False) 能夠禁用這一特性。
一個常見的問題:在進行原子事務操做前,須要優先從Redis中獲取數據,例如,假設INCR命令不存在,且須要用python編譯一個原子版本的INCR
一個不成熟的本地實現是先GET值,而後在python中增長它,而後SET值。然而,這並非一個原子性的,由於多個客戶端能夠同時作這件事情,每個客戶端都經過GET獲取相同的值。
WATCH命令提供了在開始一個事務以前監控一個或多個鍵值的能力。若是開始事務以前,任何一個key的值改變了,整個事務將被取消並拋出一個WatchError。爲了完成咱們本身客戶端的INCR命令,咱們能夠以下方式實現:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
import redis
if __name__ == '__main__':
pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
result = r.flushdb()
with r.pipeline() as pipe:
while 1:
try:
# 對序列號的鍵進行 WATCH
pipe.watch('OUR-SEQUENCE-KEY')
# WATCH 執行後,pipeline 被設置成當即執行模式直到咱們通知它從新開始緩衝命令這就容許咱們獲取序列號的值
current_value = pipe.get('OUR-SEQUENCE-KEY')
next_value = int(current_value) + 1
pipe.multi() # MULTI 命令把 pipeline 設置成緩衝模式
pipe.set('OUR-SEQUENCE-KEY', next_value)
pipe.execute()
break
except Exception:
# 必定是其它客戶端在咱們開始 WATCH 和執行 pipeline 之間修改了'OUR-SEQUENCE-KEY',最好的選擇是重試
continue
注意:WATCH期間,由於管道必須綁定到一個鏈接,特別注意,必須調用reset()使得鏈接返回到鏈接池。若是管道是做爲Context Manager(如上面的例子所示),將會自動調用reset().固然也能夠手動顯示的調用。
>>> pipe = r.pipeline()
>>> while 1:
... try:
... pipe.watch('OUR-SEQUENCE-KEY')
... ...
... pipe.execute()
... break
... except WatchError:
... continue
... finally:
... pipe.reset()
掃描迭代器
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
import redis
if __name__ == '__main__':
pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
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'
說明:相似的還有hscan_iter, sscan_iter and zscan_iter等迭代器
incr命令
示例:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
import redis
if __name__ == '__main__':
pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
r.set('num_increase_continuously', 1)
result = r.get('num_increase_continuously')
print(result)
result = r.incr('num_increase_continuously')
print(result)
result = r.incr('num_increase_continuously')
print(result)
result = r.get('num_increase_continuously')
print(result)
運行結果:
b'1'
2
3
b'3'
說明:
incr(self, key, amount=1):根據amount增長key的值,每執行一次增長amount,返回結果爲增長後的值,若是key不存在,則key的值被初始化爲amount
sadd指令
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
import redis
if __name__ == '__main__':
pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
result = r.sadd('user:user_tb', 'username')
print('result of sadd username: %s' % result)
result = r.sadd('user:user_tb', 'hobby')
print('result of sadd hobby: %s' % result)
運行結果:
result of sadd username: 1
result of sadd hobby: 1
注:
sadd(self, name, *values): 添加到value(s)到集合name中
sismember指令
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
import redis
if __name__ == '__main__':
pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
r.sadd('user:user_tb', 'username')
result = r.sismember('user:user_tb', 'username')
print(result)
注:
sismember(self, name, value):判斷value是不是name集合的成員,是則返回True,反之False
smembers指令
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
import redis
if __name__ == '__main__':
pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
r.sadd('user:user_tb', 'username')
r.sadd('user:user_tb', 'hobby')
result = r.smembers('user:user_tb')
print(result)
運行結果:
{b'username', b'hobby'}
smembers(self, name):返回集合name的全部成員
sunion指令
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
import redis
if __name__ == '__main__':
pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
r.sadd('user:user_tb', 'username')
r.sadd('user:user_tb', 'hobby')
r.sadd('order:order_goods', 'username')
result = r.sunion('order:order', 'user:user_tb')
print(result)
運行結果:
{b'hobby', b'username'}
注:
sunion(self, keys, *args):根據指定的keys返回集合的並集
sinter指令
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
import redis
if __name__ == '__main__':
pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
r.sadd('user:user_tb', 'username')
r.sadd('user:user_tb', 'hobby')
r.sadd('order:order_goods', 'username')
result = r.sinter( 'order:order_goods', 'user:user_tb')
print(result)
運行結果:
{b'username'}
注:
sinter(self, keys, *args):根據指定的keys返,返回集合交集,爲空則返回set()
hset指令
實現散列表的存儲
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'shouke'
import redis
if __name__ == '__main__':
pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
result = r.hset('user:user_tb', 'name', 'shouke')
print('result of hset: %s' % result)
r.hset('user:user_tb', 'hobby', 'music')
r.hset('user:user_tb', 'addr', '深圳')
result = r.hincrby('user:user_tb', 'signin', 1)
print('result of hincrby: %s' % result)
result = r.hincrby('user:user_tb', 'signin', 1)
print('result of hincrby: %s' % result)
result = r.hgetall('user:user_tb')
print('result of hgetall: %s' % result)
result = r.hkeys('user:user_tb')
print('result of hkeys: %s' % result)
運行結果:
result of hset: 1
result of hincrby: 1
result of hincrby: 2
result of hgetall: {b'hobby': b'music', b'addr': b'\xe6\xb7\xb1\xe5\x9c\xb3', b'name': b'shouke', b'signin': b'2'}
result of hkeys: [b'name', b'hobby', b'addr', b'signin']
注:
hincrby(self, name, key, amount=1):根據amount增長哈希name中key的值,每執行一次就增長amount,返回結果爲key增長後的值
hset(self, name, key, value):在哈希name中添加鍵值對key-value,添加成功則返回1,不然返回0
hget(self, name, key):返回哈希name中,key的值
hgetall(self, name):返回包含哈希鍵值對(name/value)的字典 pairs"
hkeys(self, name):返回哈希name中的key的列表
參考鏈接:
https://pypi.python.org/pypi/redis#downloads
http://debugo.com/python-redis/
更多資料煩查看源代碼