python redis 方法大全
redis連線
1,安裝redis
pip install redis
例項:
import redis from datetime import datetime
r = redis.Redis(host='localhost', port=6379, db=15,decode_responses=True) r.set('name', 'lvye') print(r['name']) print(r.get('name')) print(type(r.get('name')))
lvye
lvye
<class 'str'>
decode_responses=True,寫入的鍵值對中的value為str型別,不加這個引數寫入的則為位元組型別。
2、連線池
redis-py使用connection pool來管理對一個redis server的所有連線,避免每次建立、釋放連線的開銷。
預設,每個Redis例項都會維護一個自己的連線池。
可以直接建立一個連線池,然後作為引數Redis,這樣就可以實現多個Redis例項共享一個連線池
import redis pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True) # host是redis主機,需要redis服務端和客戶端都起著 redis預設埠是6379r = redis.Redis(connection_pool=pool) r.set('gender', 'male') # key是"gender" value是"male" 將鍵值對存入redis快取 print(r.get('gender')) # gender 取出鍵male對應的值
3,string redis基本命令
1,在Redis中設定值,預設,不存在則建立,存在則修改
set(name, value, ex=None, px=None, nx=False, xx=False)
引數:
- ex,過期時間(秒)
- px,過期時間(毫秒)
- nx,如果設定為True,則只有name不存在時,當前set操作才執行
- xx,如果設定為True,則只有name存在時,當前set操作才執行
2,setnx(name, value)
設定值,只有name不存在時,執行設定操作(新增)
print(r.setnx('fruit1', 'banana')) # fruit1不存在,輸出為True
白話解釋,不存在則直接建立新的,存在則返回false,不可以修改。
3,setex(name, value, time)
引數: time,期時間(數字秒 或 timedelta物件)
r.setex("fruit2", "orange", 5) time.sleep(5) print(r.get('fruit2')) # 5秒後,取值就從orange變成None
4.psetex(name, time_ms, value)
time_ms,過期時間(數字毫秒 或 timedelta物件)
r.psetex("fruit3", 5000, "apple") time.sleep(5) print(r.get('fruit3'))
5,批量設定值 mset(*args, **kwargs)
import redis r = redis.Redis(host='localhost', port=6379, db=15,decode_responses=True) r.mget({'k1': 'v1', 'k2': 'v2'}) r.mset(k1="v1", k2="v2") # 這裡k1 和k2 不能帶引號 一次設定對個鍵值對 print(r.mget("k1", "k2")) # 一次取出多個鍵對應的值 #['v1', 'v2'] print(r.mget("k1")) #['v1']
6,批量獲取值,
print(r.mget('k1', 'k2')) print(r.mget(['k1', 'k2']))
7,設定新值並獲取原來的值
r.set('name','yang')
s = r.getset('name','zhenyu')
print(s)
#yang
8,返回name對應值的位元組長度(一個漢字3個位元組)
s = r.strlen('name') print(s)
9,ncr(self, name, amount=1)
r.set("visit:12306:totals", 34634) r.incr("visit:12306:totals") r.incr("visit:12306:totals") print(r.get("visit:12306:totals"))解析: 設初始值,不指定amount 預設為1 ,上面最後輸出 34636 應用場景 – 頁面點選數
假定我們對一系列頁面需要記錄點選次數。 例如論壇的每個帖子都要記錄點選次數,而點選次數比回帖的次數的多得多。如果使用關係資料庫來儲存點選,可能存在大量的行級鎖爭用。 所以,點選數的增加使用redis的INCR命令最好不過了。 當redis伺服器啟動時,可以從關係資料庫讀入點選數的初始值(12306這個頁面被訪問了34634次) 10,incrbyfloat(self, name, amount=1.0) 自增 name對應的值,當name不存在時,則建立name=amount,否則,則自增。
r.set("foo1", "123.0") r.set("foo2", "221.0") print(r.mget("foo1", "foo2")) r.incrbyfloat("foo1", amount=2.0) r.incrbyfloat("foo2", amount=3.0) print(r.mget("foo1", "foo2")) ['123.0', '221.0'] ['125', '224']
11,decr(self, name, amount=1)
自減 name對應的值,當name不存在時,則建立name=amount,否則,則自減。
r.decr("foo5", amount=3) # 遞減3 r.decr("foo6", amount=1) # 遞減1 print(r.mget("foo5", "foo6")) #['-3', '-1']
12,append(key, value)
在redis name對應的值後面追加內容
r.append('name','yang') print(r.get('name'))
#zhenyuyang
4,hash redis基本命令
1.hset(name, key, value)
單個增加--修改(單個取出)--沒有就新增,有的話就修改
r.hset("hash1", "k1", "v1")
r.hset("hash1", "k2", "v2")
print(r.hkeys("hash1")) # 取hash中所有的key
#['k1', 'k2']
print(r.hget("hash1", "k1")) # 單個取hash的key對應的值
# v1
print(r.hmget("hash1", "k1", "k2")) # 多個取hash的key對應的值
# ['v1', 'v2']
r.hsetnx("hash1", "k3", "v3") # 只能新建
print(r.hget("hash1", "k3"))
# 這個命令只能新建,不會覆蓋原來的值
hget(name,key)
在name對應的hash中獲取根據key獲取value
hmget(name, keys, *args)
在name對應的hash中獲取多個key的值
2,hmset(name, mapping)
批量插入資料,
引數:
name,redis的name
mapping,字典,如:{'k1':'v1', 'k2': 'v2'}
r.hmset("hash2", {"k2": "v2", "k3": "v3"}) print(r.hmget('hash2','k2','k3')) #['v2', 'v3']
3,hgetall(name)
獲取所有的鍵值對
r.hmset("hash2", {"k2": "v2", "k3": "v3"}) print(r.hgetall('hash2')) #{'k2': 'v2', 'k3': 'v3'}
4,hlen(name)
獲取鍵值對長度,說白了就是計算幾個字典而已
r.hmset("hash2", {"k2": "v2", "k3": "v3"}) print(r.hgetall('hash2')) #{'k2': 'v2', 'k3': 'v3'} print(r.hlen('hash2')) #2
5,hkeys(name)
獲取所有的鍵,返回列表
r.hmset("hash2", {"k2": "v2", "k3": "v3"}) print(r.hkeys('hash2')) #['k2', 'k3']
6,hvals(name)
獲取所有的值,返回列表
r.hmset("hash2", {"k2": "v2", "k3": "v3"}) print(r.hvals('hash2')) #['v2', 'v3']
7,hexists(name, key)
判斷成員是否存在(類似字典的in)
r.hmset("hash2", {"k2": "v2", "k3": "v3"}) s = r.hexists('hash2','k2') print(s) #True
8,hdel(name,*keys)
刪除鍵值對
#{'k1': 'v1', 'k2': 'v2', 'k3': 'v3'} r.hdel("hash1", "k1") # 刪除一個鍵值對 print(r.hgetall("hash1")) #{'k2': 'v222', 'k3': 'v3', 'k11': 'v1'}
9,hincrby(name, key, amount=1)
自增name對應的hash中的指定key的值,不存在則建立key=amount
r.hset("hash1", "k3", 123) r.hincrby("hash1", "k3", amount=-1) print(r.hgetall("hash1")) #{'k3': '122'} r.hincrby("hash1", "k4", amount=1) # 不存在的話,value預設就是1 print(r.hgetall("hash1")) #{'k3': '122', 'k4': '1'}
10,hincrbyfloat(name, key, amount=1.0)
自增自減浮點數(將key對應的value--浮點數 自增1.0或者2.0,或者別的浮點數 負數就是自減)
r.hset("hash1", "k5", "1.0") r.hincrbyfloat("hash1", "k5", amount=-1.0) # 已經存在,遞減-1.0 print(r.hgetall("hash1")) #{'k5': '0'} r.hincrbyfloat("hash1", "k6", amount=-1.0) # 不存在,value初始值是-1.0 每次遞減1.0 print(r.hgetall("hash1")) #{'k5': '0', 'k6': '-1'}
11,hscan_iter(name, match=None, count=None)
利用yield封裝hscan建立生成器,實現分批去redis中獲取資料
引數:
match,匹配指定key,預設None 表示所有的key
count,每次分片最少獲取個數,預設None表示採用Redis的預設分片個數
print(r.hgetall('hash1')) #{'k5': '0', 'k6': '-1'} for item in r.hscan_iter('hash1'): print(item) #('k5', '0') #('k6', '-1') #f返回鍵值對元祖
5,list redis基本命令
1,lpush(name,values)
增加(類似於list的append,只是這裡是從左邊新增加)--沒有就新建
r = redis.Redis(host='localhost', port=6379, db=15,decode_responses=True) r.lpush("list1", 11, 22, 33) print(r.lrange('list1', 0, -1)) #['33', '22', '11']
擴充套件:
r.rpush("list2", 11, 22, 33) # 表示從右向左操作 print(r.llen("list2")) # 列表長度 print(r.lrange("list2", 0, 3)) # 切片取出值,範圍是索引號0-3
2,lpushx(name,value)
往已經有的name的列表的左邊新增元素,沒有的話無法建立
r.lpushx("list1", 11) #該list1必須存在,否則無法插入
3,rpushx(name,value)
往已經有的name的列表的右邊新增元素,沒有的話無法建立
print(r.lrange('list1',0,-1)) #['1100', '11', '33', '22', '11', '33', '22', '11', '1100'] r.rpushx("list1", 1100) #增加 print(r.lrange('list1',0,-1)) #['1100', '11', '33', '22', '11', '33', '22', '11', '1100', '1100']
4,linsert(name, where, refvalue, value))
在name對應的列表的某一個值前或後插入一個新值
引數:
name,redis的name
where,BEFORE或AFTER
refvalue,標杆值,即:在它前後插入資料
value,要插入的資料
r.linsert("list1", "before", "11", "00") #意思是在11 之前插入00
5,r.lset(name, index, value)
對name對應的list中的某一個索引位置重新賦值
引數:
name,redis的name
index,list的索引位置
value,要設定的值
print(r.lrange('list1',0,-1)) #['1100', '00', '11', '33', '22', '11', '33', '22', '11', '1100', '1100'] r.lset('list1',1,'222') #對下標1的值改為222 print(r.lrange('list1',0,-1)) #['1100', '222', '11', '33', '22', '11', '33', '22', '11', '1100', '1100']
6,r.lrem(name, value, num)
在name對應的list中刪除指定的值
引數:
name,redis的name
value,要刪除的值
num,
num=0,刪除列表中所有的指定值;
num=2,從前到後,刪除2個; num=1,從前到後,刪除左邊第1個
num=-2,從後向前,刪除2個
print(r.lrange("list1", 0, -1)) #['1100', '222', '11', '33', '22', '11', '33', '22', '11', '1100', '1100'] r.lrem('list1','1100',4) #左邊出現的11,後面指定刪除數量 print(r.lrange("list1", 0, -1)) #['1100', '222', '33', '22', '11', '33', '22', '11', '1100', '1100']
7,lpop(name)
在name對應的列表的左側獲取第一個元素並在列表中移除,返回值則是第一個元素
s = r.lpop('list1') #從左邊刪除第一個,並返回
s = r.rpop('list1') #從右邊刪除第一個,並返回
8,ltrim(name, start, end)
在name對應的列表中移除沒有在start-end索引之間的值
引數:
name,redis的name
start,索引的起始位置
end,索引結束位置
print(r.lrange("list1", 0, -1)) #['33', '22', '11', '22', '33', '22'] r.ltrim('list1',0,2) #下標0-2也就是3個數,不在這個範圍的刪除 print(r.lrange("list1", 0, -1)) #['33', '22', '11']
9,lindex(name, index)
在name對應的列表中根據索引獲取列表元素
print(r.lrange("list1", 0, -1)) #['33', '22', '11'] print(r.lindex('list1',0)) #33
10,rpoplpush(src, dst)
移動 元素從一個列表移動到另外一個列表
# list1 ['33', '22'] # list2 ['11', '5', '4', '3', '2', '1']
r.rpoplpush('list1','list2') #可以看出從第一個列表最右邊一個移到第二個列表的最左側 print(r.lrange("list1", 0, -1)) print(r.lrange("list2", 0, -1)) #['33'] #['22', '11', '5', '4', '3', '2', '1']
11,brpoplpush(src, dst, timeout=0)
移動 元素從一個列表移動到另外一個列表 可以設定超時
引數:
src,取出並要移除元素的列表對應的name
dst,要插入元素的列表對應的name
timeout,當src對應的列表中沒有資料時,阻塞等待其有資料的超時時間(秒),0 表示永遠阻塞
r.brpoplpush('list1','list2' , timeout=0) print(r.lrange("list1", 0, -1)) print(r.lrange("list2", 0, -1)) #['33']
6,set redis基本命令
1,sadd(name,values)
name對應的集合中新增元素
r.sadd("set1", 33, 44, 55, 66) # 往集合中新增元素 print(r.scard("set1")) # 集合的長度是4 print(r.smembers("set1")) # 獲取集合中所有的成員 #{'33', '55', '44', '66'}
2.獲取元素個數 類似於 len
scard(name)
獲取 name 對應的集合中元素個數
3.獲取集合中所有的成員
smembers(name)
獲取name對應的集合的所有成員
4, sscan('set1')
獲取集合中所有的成員--元組形式
r.sadd("set1", 33, 44, 55, 66) # 往集合中新增元素 print(r.sscan('set1')) #(0, ['33', '44', '55', '66'])
5,sscan_iter()
獲取集合中所有的成員--迭代器的方式
for i in r.sscan_iter('set1'): print(i) ''' 33 44 55 66 '''
6,sismember(name, value)
判斷是否是集合的成員 類似in
print(r.smembers("set2")) #{'55', '33', '66', '44'} print(r.sismember('set2', '33'))
True
7,smove(src, dst, value)
將某個成員從一個集合中移動到另外一個集合
print(r.smembers("set2")) #{'55', '66', '33', '44'} print(r.smembers("set3")) #{'11', '22', '33'} r.smove("set2", "set3", '44') #移動 print(r.smembers("set2")) #{'66', '55', '33'} print(r.smembers("set3")) #{'44', '11', '22', '33'}
8,spop(name)
從集合移除一個成員,並將其返回,說明一下,集合是無序的,所有是隨機刪除的
print(r.smembers("set2")) s = r.spop('set2') print(s) print(r.smembers("set2")) ''' {'66', '55', '33'} 66 {'55', '33'} '''
’8,srem(name, values)
刪除--指定值刪除
print(r.smembers("set2")) r.srem('set2','55') print(r.smembers("set2")) ''' {'33', '55'} {'33'} '''
7,redis基本命令 有序set
- Set操作,Set集合就是不允許重複的列表,本身是無序的
- 有序集合,在集合的基礎上,為每元素排序;元素的排序需要根據另外一個值來進行比較,
- 所以,對於有序集合,每一個元素有兩個值,即:值和分數,分數專門用來做排序。
1,zadd()
向有序集合新增元素
r.zadd("zset1", n1=11, n2=22) r.zadd("zset2", 'm1', 22, 'm2', 44) print(r.zcard("zset1")) # 集合長度 print(r.zcard("zset2")) # 集合長度 print(r.zrange("zset1", 0, -1)) # 獲取有序集合中所有元素 print(r.zrange("zset2", 0, -1, withscores=True)) # 獲取有序集合中所有元素和分數 2 2 ['n1', 'n2'] [('m1', 22.0), ('m2', 44.0)]
2.獲取有序集合元素個數 類似於len
zcard(name)
print(r.zcard("zset1")) # 集合長度
獲取name對應的有序集合元素的數量
3.r.zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)
按照索引範圍獲取name對應的有序集合的元素引數:
name,redis的name
start,有序集合索引起始位置(非分數)
end,有序集合索引結束位置(非分數)
desc,排序規則,預設按照分數從小到大排序
withscores,是否獲取元素的分數,預設只獲取元素的值
score_cast_func,對分數進行資料轉換的函式
4,zrevrange(name, start, end, withscores=False, score_cast_func=float)
同zrange,集合是從大到小排序的
r.zadd("zset1", n1=11, n2=22)
print(r.zrevrange("zset1", 0, -1)) # 只獲取元素,不顯示分數 print(r.zrevrange("zset1", 0, -1, withscores=True)) # 獲取有序集合中所有元素和分數,分數倒序 ''' ['n2', 'n1'] [('n2', 22.0), ('n1', 11.0)] '''
5,zscan_iter(name, match=None, count=None,score_cast_func=float)
獲取所有元素--迭代器
r.zadd("zset1", n1=11, n2=22) for i in r.zscan_iter("zset1"): # 遍歷迭代器 print(i) ''' ('n1', 11.0) ('n2', 22.0) '''
6,zcount(name, min, max)
獲取name對應的有序集合中分數 在 [min,max] 之間的個數
r.zadd("zset1", n1=11, n2=22) print(r.zrange("zset1", 0, -1, withscores=True)) print(r.zcount("zset1", 11, 22)) ''' [('n1', 11.0), ('n2', 22.0)] 2 '''
7,自增name對應的有序集合的 name 對應的分數
zincrby(name, value, amount)
r.zadd("zset1", n1=11, n2=22) r.zincrby("zset1", "n2", amount=2) # 每次將n2的分數自增2 print(r.zrange("zset1", 0, -1, withscores=True))
#[('n1', 11.0), ('n2', 24.0)]
8,zrank(name, value)
獲取值的索引號
r.zadd("zset1", n1=11, n2=22) print(r.zrank("zset1", "n1")) # n1的索引號是0 這裡按照分數順序(從小到大) #0 print(r.zrank("zset1", "n2")) # n2的索引號是1 #1 print(r.zrevrank("zset1", "n1")) # n1的索引號是1 這裡安照分數倒序(從大到小) #1
9,zrem(name, values)
刪除name對應的有序集合中值是values的成員
r.zadd("zset1", n1=11, n2=22) r.zrem("zset1", "n1") # 刪除有序集合中的元素n1 刪除單個 print(r.zrange("zset1", 0, -1)) #['n2']
10,zremrangebyrank(name, min, max)
刪除--根據排行範圍刪除,按照索引號來刪除
r.zadd("zset1", n1=11, n2=22,n3=33,n4=55) r.zremrangebyrank('zset1',0,2) #刪除這個區間的元素,包括2 print(r.zrange("zset1", 0, -1)) #['n4']
11,zremrangebyscore(name, min, max)
根據分數範圍刪除
r.zadd("zset1", n1=11, n2=22,n3=33,n4=55) r.zremrangebyscore('zset1',0,22) #刪除這個區間的分數,包括22 print(r.zrange("zset1", 0, -1)) #['n3', 'n4']
12,zscore(name, value)
獲取值對應的分數
r.zadd("zset1", n1=11, n2=22,n3=33,n4=55) print(r.zscore('zset1', 'n1')) #11.0
8、其他常用操作
1.刪除
delete(*names)
根據刪除redis中的任意資料型別(string、hash、list、set、有序set)
r.delete("list2") # 刪除key為gender的鍵值對
2.檢查名字是否存在
exists(name)
檢測redis的name是否存在,存在就是True,False 不存在
print(r.exists('set1'))
3.模糊匹配
keys(pattern='')更多:
KEYS * 匹配資料庫中所有 key 。
KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
KEYS hllo 匹配 hllo 和 heeeeello 等。
KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo
4.設定超時時間
expire(name ,time)
為某個redis的某個name設定超時時間
r.lpush("list5", 11, 22) r.expire("list5", time=3) print(r.lrange("list5", 0, -1)) time.sleep(3) print(r.lrange("list5", 0, -1))
5.重新命名
rename(src, dst)
對redis的name重新命名
r.lpush("list5", 11, 22) r.rename("list5", "list5-1")
6.隨機獲取name
randomkey()
隨機獲取一個redis的name(不刪除)
print(r.randomkey())
7.獲取型別
type(name)
獲取name對應值的型別
print(r.type("set1")) print(r.type("hash2"))
8.檢視所有元素
scan(cursor=0, match=None, count=None)
print(r.hscan("hash2")) print(r.sscan("set3")) print(r.zscan("zset2")) print(r.getrange("foo1", 0, -1)) print(r.lrange("list2", 0, -1)) print(r.smembers("set3")) print(r.zrange("zset3", 0, -1)) print(r.hgetall("hash1"))
9.檢視所有元素--迭代器
scan_iter(match=None, count=None)
for i in r.hscan_iter("hash1"): print(i) for i in r.sscan_iter("set3"): print(i) for i in r.zscan_iter("zset3"): print(i)
other 方法
print(r.get('name')) # 查詢key為name的值 r.delete("gender") # 刪除key為gender的鍵值對 print(r.keys()) # 查詢所有的Key print(r.dbsize()) # 當前redis包含多少條資料 r.save() # 執行"檢查點"操作,將資料寫回磁碟。儲存時阻塞 # r.flushdb() # 清空r中的所有資料
9,管道(pipeline)
redis預設在執行每次請求都會建立(連線池申請連線)和斷開(歸還連線池)一次連線操作,
如果想要在一次請求中指定多個命令,則可以使用pipline實現一次請求指定多個命令,並且預設情況下一次pipline 是原子性操作。
管道(pipeline)是redis在提供單個請求中緩衝多條伺服器命令的基類的子類。它通過減少伺服器-客戶端之間反覆的TCP資料庫包,從而大大提高了執行批量命令的功能。
import redis import time pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True) r = redis.Redis(connection_pool=pool) # pipe = r.pipeline(transaction=False) # 預設的情況下,管道里執行的命令可以保證執行的原子性,執行pipe = r.pipeline(transaction=False)可以禁用這一特性。 # pipe = r.pipeline(transaction=True) pipe = r.pipeline() # 建立一個管道 pipe.set('name', 'jack') pipe.set('role', 'sb') pipe.sadd('faz', 'baz') pipe.incr('num') # 如果num不存在則vaule為1,如果存在,則value自增1 pipe.execute() print(r.get("name")) print(r.get("role")) print(r.get("num"))
管道的命令可以寫在一起,如:
pipe.set('hello', 'redis').sadd('faz', 'baz').incr('num').execute() print(r.get("name")) print(r.get("role")) print(r.get("num"))
10,使用者瀏覽資訊快取:
先把商品id儲存
conn = get_redis_connection('history') # 2、判斷goodid是否儲存過,儲存過刪除 conn.lrem('history_%s' % user.id, 0, validated_data['goodid']) # 3、寫入goodid conn.lpush('history_%s' % user.id, validated_data['goodid']) # 4、控制儲存數量 conn.ltrim('history_%s' % user.id, 0, 4)
然後redis裡取出來
# 1、獲取使用者物件 user = request.user # 2、查詢redis獲取goodid conn = get_redis_connection('history') goodlists = conn.lrange('history_%s' % user.id, 0, 5) # [3,1,2] # 3、根據sku_id查詢商品物件 goods = GoodInfo.objects.filter(id__in=goodlists) # 4、序列化返回商品資訊 ser =self.get_serializer(goods,many=True)
寫了一天好累,部分 參考簡書上:https://www.jianshu.com/p/2639549bedc8 ,更多詳細資訊,可以參考這個網址