|
前面我們簡(jiǎn)單介紹了redis nosql數(shù)據(jù)庫(kù),現(xiàn)在我們?cè)趐ython里面來(lái)使用redis。 一、python連接redis在python中,要操作redis,目前主要是通過(guò)一個(gè)python-redis模塊來(lái)實(shí)現(xiàn) 1、在python中安裝redis模塊 1 pip3 install redis
2、在python中使用redis 跟其他模塊一樣,在安裝好redis模塊后,要使用redis模塊就要先導(dǎo)入。 python連接redis數(shù)據(jù)庫(kù): 1 #!/usr/bin/env python 2 # -*- coding:utf8 -*- 3 4 import redis 5 6 ''' 7 這種連接是連接一次就斷了,耗資源.端口默認(rèn)6379,就不用寫(xiě) 8 r = redis.Redis(host='127.0.0.1',port=6379,password='tianxuroot') 9 r.set('name','root') 10 11 print(r.get('name').decode('utf8')) 12 ''' 13 ''' 14 連接池: 15 當(dāng)程序創(chuàng)建數(shù)據(jù)源實(shí)例時(shí),系統(tǒng)會(huì)一次性創(chuàng)建多個(gè)數(shù)據(jù)庫(kù)連接,并把這些數(shù)據(jù)庫(kù)連接保存在連接池中,當(dāng)程序需要進(jìn)行數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)時(shí), 16 無(wú)需重新新建數(shù)據(jù)庫(kù)連接,而是從連接池中取出一個(gè)空閑的數(shù)據(jù)庫(kù)連接 17 ''' 18 pool = redis.ConnectionPool(host='127.0.0.1',password='helloworld') #實(shí)現(xiàn)一個(gè)連接池 19 20 r = redis.Redis(connection_pool=pool) 21 r.set('foo','bar') 22 print(r.get('foo').decode('utf8'))
二、Redis API使用redis-py 的API的使用可以分類(lèi)為:
前面通過(guò)一個(gè)連接實(shí)例來(lái)簡(jiǎn)述了python用過(guò)redis模塊連接redis數(shù)據(jù)庫(kù)的連接方式和連接池。 接下來(lái)主要看如何通過(guò)python來(lái)操作redis數(shù)據(jù)庫(kù): 1. String操作redis中的String在在內(nèi)存中按照一個(gè)name對(duì)應(yīng)一個(gè)value來(lái)存儲(chǔ)。如圖:
set(name, value, ex=None, px=None, nx=False, xx=False)
在Redis中設(shè)置值,默認(rèn),不存在則創(chuàng)建,存在則修改
參數(shù):
ex,過(guò)期時(shí)間(秒)
px,過(guò)期時(shí)間(毫秒)
nx,如果設(shè)置為T(mén)rue,則只有name不存在時(shí),當(dāng)前set操作才執(zhí)行
xx,如果設(shè)置為T(mén)rue,則只有name存在時(shí),崗前set操作才執(zhí)行
setnx(name, value)
#設(shè)置值,只有name不存在時(shí),執(zhí)行設(shè)置操作(添加)
setex(name, value, time)
2. Hash操作 hash表現(xiàn)形式上有些像pyhton中的dict,可以存儲(chǔ)一組關(guān)聯(lián)性較強(qiáng)的數(shù)據(jù) , redis中Hash在內(nèi)存中的存儲(chǔ)格式如下圖:
hset(name, key, value) # name對(duì)應(yīng)的hash中設(shè)置一個(gè)鍵值對(duì)(不存在,則創(chuàng)建;否則,修改), 注意: 在python中,鍵值對(duì)是dict, 這里的name必須是dict格式。eg:xxx[]、 xxx[k]... # 參數(shù): # name,redis的name #key,name對(duì)應(yīng)的hash中的key # value,name對(duì)應(yīng)的hash中的value # 注: # hsetnx(name, key, value),當(dāng)name對(duì)應(yīng)的hash中不存在當(dāng)前key時(shí)則創(chuàng)建(相當(dāng)于添加) hmset(name, mapping) # 在name對(duì)應(yīng)的hash中批量設(shè)置鍵值對(duì) # 參數(shù): # name,redis的name # mapping,字典,如:{'k1':'v1', 'k2': 'v2'} # 如: # r.hmset('xx', {'k1':'v1', 'k2': 'v2'}) hget(name,key) # 在name對(duì)應(yīng)的hash中獲取根據(jù)key獲取value hmget(name, keys, *args) # 在name對(duì)應(yīng)的hash中獲取多個(gè)key的值 # 參數(shù): # name,reids對(duì)應(yīng)的name # keys,要獲取key集合,如:['k1', 'k2', 'k3'] # *args,要獲取的key,如:k1,k2,k3 # 如: # r.mget('xx', ['k1', 'k2']) # 或 # print r.hmget('xx', 'k1', 'k2') hgetall(name) #獲取name對(duì)應(yīng)hash的所有鍵值 hlen(name) # 獲取name對(duì)應(yīng)的hash中鍵值對(duì)的個(gè)數(shù) hkeys(name) # 獲取name對(duì)應(yīng)的hash中所有的key的值 hvals(name) # 獲取name對(duì)應(yīng)的hash中所有的value的值 hexists(name, key) # 檢查name對(duì)應(yīng)的hash是否存在當(dāng)前傳入的key hdel(name,*keys) # 將name對(duì)應(yīng)的hash中指定key的鍵值對(duì)刪除 hincrby(name, key, amount=1) # 自增name對(duì)應(yīng)的hash中的指定key的值,不存在則創(chuàng)建key=amount # 參數(shù): # name,redis中的name # key, hash對(duì)應(yīng)的key # amount,自增數(shù)(整數(shù)) hincrbyfloat(name, key, amount=1.0) # 自增name對(duì)應(yīng)的hash中的指定key的值,不存在則創(chuàng)建key=amount # 參數(shù): # name,redis中的name # key, hash對(duì)應(yīng)的key # amount,自增數(shù)(浮點(diǎn)數(shù)) # 自增name對(duì)應(yīng)的hash中的指定key的值,不存在則創(chuàng)建key=amount hscan(name, cursor=0, match=None, count=None) Start a full hash scan with: HSCAN myhash 0 Start a hash scan with fields matching a pattern with: HSCAN myhash 0 MATCH order_* Start a hash scan with fields matching a pattern and forcing the scan command to do more scanning with: HSCAN myhash 0 MATCH order_* COUNT 1000 # 增量式迭代獲取,對(duì)于數(shù)據(jù)大的數(shù)據(jù)非常有用,hscan可以實(shí)現(xiàn)分片的獲取數(shù)據(jù),并非一次性將數(shù)據(jù)全部獲取完,從而放置內(nèi)存被撐爆 # 參數(shù): # name,redis的name # cursor,游標(biāo)(基于游標(biāo)分批取獲取數(shù)據(jù)) # match,匹配指定key,默認(rèn)None 表示所有的key # count,每次分片最少獲取個(gè)數(shù),默認(rèn)None表示采用Redis的默認(rèn)分片個(gè)數(shù) # 如: # 第一次:cursor1, data1 = r.hscan('xx', cursor=0, match=None, count=None) # 第二次:cursor2, data1 = r.hscan('xx', cursor=cursor1, match=None, count=None) # ... # 直到返回值cursor的值為0時(shí),表示數(shù)據(jù)已經(jīng)通過(guò)分片獲取完畢 hscan_iter(name, match=None, count=None) # 利用yield封裝hscan創(chuàng)建生成器,實(shí)現(xiàn)分批去redis中獲取數(shù)據(jù) # 參數(shù): # match,匹配指定key,默認(rèn)None 表示所有的key # count,每次分片最少獲取個(gè)數(shù),默認(rèn)None表示采用Redis的默認(rèn)分片個(gè)數(shù) # 如: # for item in r.hscan_iter('xx'): # print item
3. listList操作,redis中的List在在內(nèi)存中按照一個(gè)name對(duì)應(yīng)一個(gè)List來(lái)存儲(chǔ)。如圖:
lpush(name,values) # 在name對(duì)應(yīng)的list中添加元素,每個(gè)新的元素都添加到列表的最左邊 # 如: # r.lpush('oo', 11,22,33) # 保存順序?yàn)? 33,22,11 # 擴(kuò)展: # rpush(name, values) 表示從右向左操作 lpushx(name,value) # 在name對(duì)應(yīng)的list中添加元素,只有name已經(jīng)存在時(shí),值添加到列表的最左邊
4.set集合操作Set操作,Set集合就是不允許重復(fù)的列表。這里包括了一般的集合和有序集合。 sadd(name,values) # name對(duì)應(yīng)的集合中添加元素 scard(name) #獲取name對(duì)應(yīng)的集合中元素個(gè)數(shù) sdiff(keys, *args) #在第一個(gè)name對(duì)應(yīng)的集合中且不在其他name對(duì)應(yīng)的集合的元素集合 sdiffstore(dest, keys, *args) # 獲取第一個(gè)name對(duì)應(yīng)的集合中且不在其他name對(duì)應(yīng)的集合,再將其新加入到dest對(duì)應(yīng)的集合中 sinter(keys, *args) # 獲取多一個(gè)name對(duì)應(yīng)集合的并集 sinterstore(dest, keys, *args) # 獲取多一個(gè)name對(duì)應(yīng)集合的并集,再講其加入到dest對(duì)應(yīng)的集合中 sismember(name, value) # 檢查value是否是name對(duì)應(yīng)的集合的成員 smembers(name) # 獲取name對(duì)應(yīng)的集合的所有成員 smove(src, dst, value) # 將某個(gè)成員從一個(gè)集合中移動(dòng)到另外一個(gè)集合 spop(name) # 從集合的右側(cè)(尾部)移除一個(gè)成員,并將其返回 srandmember(name, numbers) # 從name對(duì)應(yīng)的集合中隨機(jī)獲取 numbers 個(gè)元素 srem(name, values) # 在name對(duì)應(yīng)的集合中刪除某些值 sunion(keys, *args) # 獲取多一個(gè)name對(duì)應(yīng)的集合的并集 sunionstore(dest,keys, *args) # 獲取多一個(gè)name對(duì)應(yīng)的集合的并集,并將結(jié)果保存到dest對(duì)應(yīng)的集合中 sscan(name, cursor=0, match=None, count=None) sscan_iter(name, match=None, count=None) # 同字符串的操作,用于增量迭代分批獲取元素,避免內(nèi)存消耗太大
zadd(name, *args, **kwargs) # 在name對(duì)應(yīng)的有序集合中添加元素 # 如: # zadd('zz', 'n1', 1, 'n2', 2) # 或 # zadd('zz', n1=11, n2=22) zcard(name) # 獲取name對(duì)應(yīng)的有序集合元素的數(shù)量 zcount(name, min, max) # 獲取name對(duì)應(yīng)的有序集合中分?jǐn)?shù) 在 [min,max] 之間的個(gè)數(shù) zincrby(name, value, amount) # 自增name對(duì)應(yīng)的有序集合的 name 對(duì)應(yīng)的分?jǐn)?shù) r.zrange( name, start, end, desc=False, withscores=False, score_cast_func=float) # 按照索引范圍獲取name對(duì)應(yīng)的有序集合的元素 # 參數(shù): # name,redis的name # start,有序集合索引起始位置(非分?jǐn)?shù)) # end,有序集合索引結(jié)束位置(非分?jǐn)?shù)) # desc,排序規(guī)則,默認(rèn)按照分?jǐn)?shù)從小到大排序 # withscores,是否獲取元素的分?jǐn)?shù),默認(rèn)只獲取元素的值 # score_cast_func,對(duì)分?jǐn)?shù)進(jìn)行數(shù)據(jù)轉(zhuǎn)換的函數(shù) # 更多: # 從大到小排序 # zrevrange(name, start, end, withscores=False, score_cast_func=float) # 按照分?jǐn)?shù)范圍獲取name對(duì)應(yīng)的有序集合的元素 # zrangebyscore(name, min, max, start=None, num=None, withscores=False, score_cast_func=float) # 從大到小排序 # zrevrangebyscore(name, max, min, start=None, num=None, withscores=False, score_cast_func=float) zrank(name, value) # 獲取某個(gè)值在 name對(duì)應(yīng)的有序集合中的排行(從 0 開(kāi)始) # 更多: # zrevrank(name, value),從大到小排序 zrem(name, values) # 刪除name對(duì)應(yīng)的有序集合中值是values的成員 # 如:zrem('zz', ['s1', 's2']) zremrangebyrank(name, min, max) # 根據(jù)排行范圍刪除 zremrangebyscore(name, min, max) # 根據(jù)分?jǐn)?shù)范圍刪除 zscore(name, value) # 獲取name對(duì)應(yīng)有序集合中 value 對(duì)應(yīng)的分?jǐn)?shù) zinterstore(dest, keys, aggregate=None) # 獲取兩個(gè)有序集合的交集,如果遇到相同值不同分?jǐn)?shù),則按照aggregate進(jìn)行操作 # aggregate的值為: SUM MIN MAX zunionstore(dest, keys, aggregate=None) # 獲取兩個(gè)有序集合的并集,如果遇到相同值不同分?jǐn)?shù),則按照aggregate進(jìn)行操作 # aggregate的值為: SUM MIN MAX zscan(name, cursor=0, match=None, count=None, score_cast_func=float) zscan_iter(name, match=None, count=None,score_cast_func=float) # 同字符串相似,相較于字符串新增score_cast_func,用來(lái)對(duì)分?jǐn)?shù)進(jìn)行操作
5、其他常用操作
delete(*names) # 根據(jù)刪除redis中的任意數(shù)據(jù)類(lèi)型 exists(name) # 檢測(cè)redis的name是否存在 keys(pattern='*') # 根據(jù)模型獲取redis的name # 更多: # KEYS * 匹配數(shù)據(jù)庫(kù)中所有 key 。 # KEYS h?llo 匹配 hello , hallo 和 hxllo 等。 # KEYS h*llo 匹配 hllo 和 heeeeello 等。 # KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo expire(name ,time) # 為某個(gè)redis的某個(gè)name設(shè)置超時(shí)時(shí)間 rename(src, dst) # 對(duì)redis中src的name重命名為dst move(name, db)) # 將redis的某個(gè)值移動(dòng)到指定的db下 randomkey() # 隨機(jī)獲取一個(gè)redis的name(不刪除) type(name) # 獲取name對(duì)應(yīng)值的類(lèi)型 scan(cursor=0, match=None, count=None) scan_iter(match=None, count=None) # 同字符串操作,用于增量迭代獲取key
三、管道 redis-py默認(rèn)在執(zhí)行每次請(qǐng)求都會(huì)創(chuàng)建(連接池申請(qǐng)連接)和斷開(kāi)(歸還連接池)一次連接操作,如果想要在一次請(qǐng)求中指定多個(gè)命令,則可以使用pipline實(shí)現(xiàn)一次請(qǐng)求指定多個(gè)命令,并且默認(rèn)情況下一次pipline 是原子性操作。 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import redis 5 6 pool = redis.ConnectionPool(host='192.168.22.132', port=6379) 7 r = redis.Redis(connection_pool=pool) 8 9 # pipe = r.pipeline(transaction=False) 10 pipe = r.pipeline(transaction=True) 11 12 pipe.set('name', 'root') 13 pipe.set('role', 'root') 14 15 pipe.execute()
四、發(fā)布與訂閱
發(fā)布者:服務(wù)器 訂閱者:Dashboad和數(shù)據(jù)處理 redis_helper: 1 #!/usr/bin/env python 2 # -*- coding:utf8 -*- 3 4 import redis 5 6 class RedisHelper(object): 7 8 def __init__(self): 9 self.__conn = redis.Redis(host='localhost') #連接本機(jī),ip不用寫(xiě) 10 self.chan_sub = 'fm104.5' 11 self.chan_pub = 'fm86' #這個(gè)頻道沒(méi)用到啊... 12 13 def public(self,msg): 14 self.__conn.publish(self.chan_sub,msg) 15 return True 16 17 def subscribe(self): 18 pub = self.__conn.pubsub() 19 pub.subscribe(self.chan_sub) #訂閱的頻道 20 pub.parse_response() #準(zhǔn)備好監(jiān)聽(tīng)(再調(diào)用一次就是開(kāi)始監(jiān)聽(tīng)) 21 return pub redis訂閱: 1 #!/usr/bin/env python 2 # -*- coding:utf8 -*- 3 4 from redis_helper import RedisHelper 5 6 obj = RedisHelper() 7 redis_sub = obj.subscribe() 8 9 while True: 10 msg = redis_sub.parse_response() 11 print(msg) #[b'message', b'fm104.5', b'who are you?'] 12 # print(msg[2].decode('utf8')) redis發(fā)布: 1 #!/usr/bin/env python 2 # -*- coding:utf8 -*- 3 4 ''' 5 發(fā)布與訂閱是不同于存值取值,存值取值不需要同步,發(fā)布與訂閱是需要同步的 6 ''' 7 ''' 8 #這樣是可以的,為了配套,使用下面的 9 import redis 10 11 obj = redis.Redis(password='helloworld') 12 obj.publish('fm104.5','hello') 13 14 ''' 15 16 from redis_helper import RedisHelper 17 18 obj = RedisHelper() 19 obj.public('hello')
|
|
|