什么是Redis?
Redis是一款開源的、高性能的鍵-值存儲(key-value store)。它常被稱作是一款數據結構服務器(data structure server)。
Redis的鍵值可以包括字符串(strings)類型,同時它還包括哈希(hashes)、列表(lists)、集合(sets)和 有序集合(sorted sets)等數據類型。 對於這些數據類型,你可以執行原子操作。例如:對字符串進行附加操作(append);遞增哈希中的值;向列表中增加元素;計算集合的交集、並集與差集等。
redis = { 'k1':'zrg', #字符串 'k2':['z','r','g'], #列表 'k3':{1,2,3,4}, #集合 'k4':{'name':'zrg','age':25}, #字典/哈希表 'k5':{('zrg',25),('yj',26)} #有序集合 }
為了獲得優異的性能,Redis采用了內存中(in-memory)數據集(dataset)的方式。同時,Redis支持數據的持久化(可以保存到硬盤上),你可以每隔一段時間將數據集轉存到磁盤上(snapshot),或者在日志尾部追加每一條操作命令(append only file,aof)。
Redis同樣支持主從復制(master-slave replication),並且具有非常快速的非阻塞首次同步( non-blocking first synchronization)、網絡斷開自動重連等功能。同時Redis還具有其它一些特性,其中包括簡單的事物支持、發布訂閱 ( pub/sub)、管道(pipeline)和虛擬內存(vm)等 。
Redis具有豐富的客戶端,支持現階段流行的大多數編程語言。
一、redis 安裝
windoes 安裝
一般情況下不是開發人員安裝,而且也不是安裝在Windows平台下,一般來說是安裝在Linux平台下,而且是運維人員來做這個事。
二、Redis操作
Redis的數據類型:
Keys
非二進制安全的字符類型( not binary-safe strings )
Values
Strings
Lists
Sets
Sorted sets
Hash
redis本質上一個key-value 數據庫,所以我們首先來看看他的key.首先key也是字符串類型,由於key不是binary safe的字符串,所以像“my key”和“mykey\n”這樣包含空格和換行的key是不允許的。
我們在使用的時候可以自己定義一個Key的格式。例如 object-type:id:field
Key不要太長。占內存,查詢慢。
Key不要太短。u:1000:pwd 不如 user:1000:password 可讀性好
安裝redis模塊:
pip3 install redis
import redis # 拿到redis鏈接 coon = redis.Redis(host='127.0.0.1',port=6379) # 朝內存數據庫存放key是name,value是zrg,的字符串 coon.set('name','zrg')
不通過Python也可以通過命令來執行。
連接池:
import redis # 連接池 pool = redis.ConnectionPool(host='127.0.0.1',port=6379) # 從池子里拿一個連接 coon = redis.Redis(connection_pool=pool) # 正常情況下pool做成單例! # 方法1、寫到模塊里,以模塊形式導過來 # 方法2、寫一個類get一個單例的pool,return回來。
存儲是Bytes格式
1、字符串操作
1.1 set(key,value,ex=None,px=None,nx=False,xx=False)
在redis中設置值,默認,不存在則創建,存在則修改:
參數:
ex,過期時間(秒)
px,過期時間(毫秒)
nx,如果設置為True,則只有key不存在時,當前set操作才執行,值存在,就修改不了,執行沒效果。
xx,如果設置為True,則只有key存在時,當前set操作才執行,值存在才能修改,值不存在,不會設置新值。
1.2 setex(key,time,value)
1.3 psetex(key,time_ms,value) 或者是timedelta對象。
import datetime v = datetime.timedelta(seconds=5) current_time = datetime.datetime.now() current_time+v #就是五秒之后的時間
1.4 mset(*args,**kwargs) 批量設置(存) 跟set區別,set只能放一個。
import redis # 連接池 pool = redis.ConnectionPool(host='127.0.0.1',port=6379) # 從池子里拿一個連接 coon = redis.Redis(connection_pool=pool) coon.mset({'Language':'English','Title':'Python book','Pages':450})
1.5 mget(key,*args) 接收以位置傳的多個參數。看源碼!---->判斷key值到底是個列表還是單一個值
import redis # 連接池 pool = redis.ConnectionPool(host='127.0.0.1',port=6379) # 從池子里拿一個連接 coon = redis.Redis(connection_pool=pool) values = coon.mget('name','Language','Title','Pages') print(values)
1.6 getset(key,value)設置新值並獲取原來的值
1.7 getrange(key,start,end) 獲取子序列,根據字節取,非字符。
1.8 setrange(key,offset,value)修改字符串內容,從指定字符串索引開始向后替換(新值太長時,則向后添加)參數 offset,字符串的索引,字節(一個漢字三個字節) value,要設置的值
1.9 setbit(key,offset,value) 對key對應值得二進制表示的位進行操作 參數value的值只能是1或0.
1.20 getbiyt(key,offset,value)
1.21 bitop
1.22 strlen(name) 返回字符串的長度
1.23 incr(self,name,amount=1) 自增 不寫默認1 文章閱讀數用這個,提高網站性能。amount必須是整數
1.24 append(key,value)朝字符串里追加內容。
。
。
。
2、列表操作
存值方式:
2.1 lpush(key,values)
# 在name對應的list中添加元素,每個新的元素都添加到列表的最左邊 # 如: # r.lpush('oo', 11,22,33) # 保存順序為: 33,22,11 # 擴展: # rpush(name, values) 表示從右向左操作
2.2 lpushx
# 在name對應的list中添加元素,只有name已經存在時,值添加到列表的最左邊 # 更多: # rpushx(name, value) 表示從右向左操作
2.3 llen(name)
# name對應的list元素的個數
2.4 linsert(name, where, refvalue, value))
# 在name對應的列表的某一個值前或后插入一個新值 # 參數: # name,redis的name # where,BEFORE或AFTER(小寫也可以) # refvalue,標桿值,即:在它前后插入數據(如果存在多個標桿值,以找到的第一個為准) # value,要插入的數據
2.5 lset(name, index, value)
# 對name對應的list中的某一個索引位置重新賦值 # 參數: # name,redis的name # index,list的索引位置 # value,要設置的值
2.6 r.lrem(name, value, num)
# 在name對應的list中刪除指定的值 # 參數: # name,redis的name # value,要刪除的值 # num, num=0,刪除列表中所有的指定值; # num=2,從前到后,刪除2個; # num=-2,從后向前,刪除2個
2.7 lpop(name)
# 在name對應的列表的左側獲取第一個元素並在列表中移除,返回值則是第一個元素 # 更多: # rpop(name) 表示從右向左操作
2.8 lindex(name, index)
在name對應的列表中根據索引獲取列表元素
2.9 lrange(name, start, end)
# 在name對應的列表分片獲取數據 # 參數: # name,redis的name # start,索引的起始位置 # end,索引結束位置 print(re.lrange('aa',0,re.llen('aa'))
2.10 ltrim(name, start, end)
# 在name對應的列表中移除沒有在start-end索引之間的值 # 參數: # name,redis的name # start,索引的起始位置 # end,索引結束位置(大於列表長度,則代表不移除任何)
2.11 rpoplpush(src, dst)
# 從一個列表取出最右邊的元素,同時將其添加至另一個列表的最左邊 # 參數: # src,要取數據的列表的name # dst,要添加數據的列表的name
2.12 blpop(keys, timeout)
# 將多個列表排列,按照從左到右去pop對應列表的元素 # 參數: # keys,redis的name的集合 # timeout,超時時間,當元素所有列表的元素獲取完之后,阻塞等待列表內有數據的時間(秒), 0 表示永遠阻塞 # 更多: # r.brpop(keys, timeout),從右向左獲取數據 爬蟲實現簡單分布式:多個url放到列表里,往里不停放URL,程序循環取值,但是只能一台機器運行取值,可以把url放到redis中,多台機器從redis中取值,爬取數據,實現簡單分布式
2.13 brpoplpush(src, dst, timeout=0)
# 從一個列表的右側移除一個元素並將其添加到另一個列表的左側 # 參數: # src,取出並要移除元素的列表對應的name # dst,要插入元素的列表對應的name # timeout,當src對應的列表中沒有數據時,阻塞等待其有數據的超時時間(秒),0 表示永遠阻塞
2.14 自定義增量迭代
# 由於redis類庫中沒有提供對列表元素的增量迭代,如果想要循環name對應的列表的所有元素,那么就需要: # 1、獲取name對應的所有列表 # 2、循環列表 # 但是,如果列表非常大,那么就有可能在第一步時就將程序的內容撐爆,所有有必要自定義一個增量迭代的功能: import redis conn=redis.Redis(host='127.0.0.1',port=6379) # conn.lpush('test',*[1,2,3,4,45,5,6,7,7,8,43,5,6,768,89,9,65,4,23,54,6757,8,68]) # conn.flushall() def scan_list(name,count=2): index=0 while True: data_list=conn.lrange(name,index,count+index-1) if not data_list: return index+=count for item in data_list: yield item print(conn.lrange('test',0,100)) for item in scan_list('test',5): print('---') print(item)
3、字典操作
存儲格式:
只支持一層的物種數據類型
3.1 hset(name,key,value) name對應的hash中設置一個鍵值對(不存在,則創建,否則,修改)
參數:
name,redis的name
key,name對應的hash中的key
value,name對應的hash中的value
注:hsetnx(name,key,value),當name對應的hash中不存在當前key時則創建(相當於添加)
import redis # 連接池 pool = redis.ConnectionPool(host='127.0.0.1',port=6379) # 從池子里拿一個連接 coon = redis.Redis(connection_pool=pool) coon.hset('people','age','24') coon.hset('people','name','yangjing') coon.hset('people','height','158')
3.2 hmset(name,mapping) 批量設值
參數:
name,redis中的name
mapping,字典,如:{'k1':'v1','k2':'v2'}
import redis # 連接池 pool = redis.ConnectionPool(host='127.0.0.1',port=6379) # 從池子里拿一個連接 coon = redis.Redis(connection_pool=pool) coon.hmset('book',{'name':'紅樓夢','price':'123','ahthor':'曹雪芹'})
3.3 hget(name,key) 在對應的hash中根據key獲取value
3.4 hmget(name,keys,*args) 批量的取值
import redis # 連接池 pool = redis.ConnectionPool(host='127.0.0.1',port=6379) # 從池子里拿一個連接 coon = redis.Redis(connection_pool=pool) # coon.hmset('book',{'name':'紅樓夢','price':'123','ahthor':'曹雪芹'}) # values = coon.hmget('book','name','price','ahthor') values = coon.hmget('book',['name','price','ahthor']) print(values)
3.5 hgetall(name) 取出name對應hash的所有鍵值
3.6 hlen(name)獲取對應的hash中鍵值對的個數
3.7 hkeys(name)返回左右key
3.8 hvals(name)返回所有value
3.9 hexisits(name,key)判斷這個hash的key在不在
3.10 hdel(name,*keys)刪除指定的鍵值對
3.11 hinrby(name,key,amount=1)
import redis # 連接池 pool = redis.ConnectionPool(host='127.0.0.1',port=6379) # 從池子里拿一個連接 coon = redis.Redis(connection_pool=pool) # coon.hincrby('people','age',amount=1) # coon.hincrby('people','age')
3.12 hscan(name,cursor=0,match=None,count=None) 增量迭代獲取
增量式迭代獲取,對於數據大的數據非常有用,hscan可以實現分片的獲取數據,並非一次性將數據全部獲取完
參數:
name,redis的name
cursor,游標(基於游標分批次獲取數據)
match,匹配指定key,默認None,表示所有的key
count,每次分片最少獲取個數,默認None表示采用redis的默認分片個數
3.13 hscan_iter(name,match=None,count=None)
三、管道
redis.py 默認在執行每一次請求都會創建(連接池申請連接)和斷開(歸還連接池)一次連續操作,如果想要在一次請求中指定多個命令,則可以使用pipline實現一次請求指定多個命令,並且默認情況下一次()事務pipline都是原子性(都成功或都不成功)操作。
import redis # 事務 coon = redis.Redis(host='127.0.0.1',port=6379) # 拿到一個管道,transaction、 pi = coon.pipeline(transaction=True) # 說明是批量命令 pi.multi() pi.set('author','作者') pi.set('publish','出版社') # 執行 pi.execute()
四、Django中使用redis
第一種方式:通用的
1.先做成單例
在一個文件夾里寫一個py文件
import redis POOL = redis.ConnectionPool(host='127.0.0.1',port=6379)
2. views.py 里使用的時候導過來
import redis from api.utils import pool # 從池子里拿一個連接 coon = redis.Redis(connection_pool=pool)
3. 寫路由
第二種方式 django-redis 模塊 但是需要配置,寫到settings.py里
CACHES = { "default":{ "BACKEND":"django_redis.cache.RedisCache", "LOCATION":"redis://127.0.0.1:6379", "OPTIONS":{ "CLIENT_CLSAA":"diango_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS":{"max_connections":100}, # "PASSWORD":'121352', } } }
views.py
import redis from django_redis import get_redis_connection coon = get_redis_connection()
五、其他操作
delete(*names) 根據key值刪數據類型
# 根據刪除redis中的任意數據類型
exists(name)
# 檢測redis的name是否存在
keys(pattern='*')
# 根據模型獲取redis的name # 更多: # KEYS * 匹配數據庫中所有 key 。 # KEYS h?llo 匹配 hello , hallo 和 hxllo 等。 # KEYS h*llo 匹配 hllo 和 heeeeello 等。 # KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo
expire(name ,time)
# 為某個redis的某個name設置超時時間
rename(src, dst)
# 對redis的name重命名為
move(name, db))
# 將redis的某個值移動到指定的db下
randomkey()
# 隨機獲取一個redis的name(不刪除)
type(name)
# 獲取name對應值的類型
scan(cursor=0, match=None, count=None)
scan_iter(match=None, count=None)
# 同字符串操作,用於增量迭代獲取key