1. 程式人生 > >python redis 方法大全

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預設埠是6379
r = 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 ,更多詳細資訊,可以參考這個網址