一、Redis
Redis 是一個 key-value 的儲存系統,和Memcached類似,value 有五大資料型別,並且資料都是快取在記憶體中。
- string(字串)
- list(連結串列)
- set(集合)
- zset(有序集合)
- hash(雜湊型別)
Redis 的好處特點
好處:
- 速度快:因為資料儲存在記憶體中。
- 有豐富的資料型別:五大資料型別。
- 支援事物:操作都是原子性,也就是說要麼都成功,要麼都失敗。
- 豐富的特性:可用於快取,訊息,按 key 設定過期時間,過期後自動刪除。
特點:
- 可以持久化
- 單執行緒、單程式
與Memcached比較
- Memcached 只支援一種資料型別字串
- Memcached 不支援持久化(不支援存到硬碟上,只要一斷電,資料就沒了)
二、python 操作 Redis
普通連線
from redis import Redis
# 簡單使用
conn = Redis(host='127.0.0.1', port=6379)
ret = conn.get('name') # 取出
print(ret)
# 輸出
b'xiaoyang'
Redis連線池
為了避免每次建立,釋放連線的開銷,所以就需要建立一個連線池,每次都從連線池中拿連線操作
由於 POOL 必須是單例的,每次拿都是拿原來那個池子裡的,所以 POOL 要寫成一個模組
redis_pool.py
import redis
# 生成一個池子物件最多能放100個連線
POOL = redis.ConnectionPool(host='127.0.0.1', port=6379,max_connections=100)
test.py
from redis import Redis
from redis_pool import POOL
conn = Redis(connection_pool=POOL) # 只要執行這句話,就是從池中拿出一個連線
ret = conn.get('name')
print(ret)
# 輸出
b'xiaoyang'
常用String 操作
set(name, value, ex=None, px=None, nx=False, xx=False)
在Redis中設定值,預設,不存在則建立,存在則修改
引數:
ex,過期時間(秒)
px,過期時間(毫秒)
nx,如果設定為True,則只有name不存在時,當前set操作才執行,值存在,就修改不了,執行沒效果
xx,如果設定為True,則只有name存在時,當前set操作才執行,值存在才能修改,值不存在,不會設定新值
mset(*args, **kwargs)
批量設定值
如:
mset(k1='v1', k2='v2')
或
mget({'k1': 'v1', 'k2': 'v2'})
get(name)
獲取值
mget(keys, *args)
批量獲取
如:
mget('k1', 'k2')
或
r.mget(['k3', 'k4'])
getset(name, value)
設定新值並獲取原來的值
bitop(operation, dest, *keys)
獲取多個值,並將值做位運算,將最後的結果儲存至新的name對應的值
引數:
operation,AND(並) 、 OR(或) 、 NOT(非) 、 XOR(異或)
dest, 新的Redis的name
*keys,要查詢的Redis的name
# 如:獲取Redis中n1,n2,n3對應的值,然後講所有的值做位運算(求並集),然後將結果儲存 new_name 對應的值中
bitop("AND", 'new_name', 'n1', 'n2', 'n3')
strlen(name)
返回name對應值的位元組長度(一個漢字3個位元組)
incr(self, name, amount=1)
自增 name對應的值,當name不存在時,則建立name=amount,否則,則自增。
引數:
name,Redis的name
amount,自增數(必須是整數)
注:
同incrby
incrbyfloat 自增浮點型
decr(self, name, amount=1)
自減 name對應的值,當name不存在時,則建立name=amount,否則,則自減。
引數:
name,Redis的name
amount,自減數(整數)
append(key, value)
在redis name對應的值後面追加內容
引數:
key, redis的name
value, 要追加的字串
常用Hash操作
hset(name, key, value)
name對應的hash中設定一個鍵值對(不存在,則建立;否則,修改)
引數:
name,redis的name
key,name對應的hash中的key
value,name對應的hash中的value
注:
hsetnx(name, key, value),當name對應的hash中不存在當前key時則建立(相當於新增)
hmset(name, mapping)
在name對應的hash中批量設定鍵值對
引數:
name,redis的name
mapping,字典,如:{'k1':'v1', 'k2': 'v2'}
如:
conn.hmset('xx', {'k1':'v1', 'k2': 'v2'})
hget(name,key)
在name對應的hash中獲取根據key獲取value
hmget(name, keys, *args)
在name對應的hash中獲取多個key的值
引數:
name,reids對應的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對應hash的所有鍵值
hscan_iter(name, match=None, count=None)
利用yield封裝hscan建立生成器,實現分批去redis中獲取資料
引數:
match,匹配指定key,預設None 表示所有的key
count,每次分片最少獲取個數,預設None表示採用Redis的預設分片個數
如:
for item in r.hscan_iter('xx'):
print item
hincrby(name, key, amount=1)
自增name對應的hash中的指定key的值,不存在則建立key=amount
引數:
name,redis中的name
key, hash對應的key
amount,自增數(整數)
注:
hincrbyfloat(name, key, amount=1.0) 自增浮點型
hlen(name):獲取 name 對應的hash中鍵值對的個數
hkeys(name):獲取 name 對應的 hash 中所有的 key 的值
hvals(name):獲取 name 對應的 hash 中所有的 value 的值
hexists(name, key):檢查 name 對應的 hash 是否存在當前傳入的 key
hdel(name,*keys):將 name 對應的 hash 中指定 key 的鍵值對刪除
常用List操作
lpush(name,values)
在name對應的list中新增元素,每個新的元素都新增到列表的最左邊
如:
conn.lpush('oo', 11,22,33)
儲存順序為: 33,22,11
擴充套件:
rpush(name, values) 表示從右向左操作
lpushx(name,value)
在name對應的list中新增元素,只有name已經存在時,值新增到列表的最左邊
更多:
rpushx(name, value) 表示從右向左操作
lpop(name)
在name對應的列表的左側獲取第一個元素並在列表中移除,返回值則是第一個元素
更多:
rpop(name) 表示從右向左操作
blpop(keys, timeout)
將多個列表排列,按照從左到右去pop對應列表的元素
引數:
keys,redis的name的集合
timeout,超時時間,當元素所有列表的元素獲取完之後,阻塞等待列表內有資料的時間(秒), 0 表示永遠阻塞
lrange(name, start, end)
在name對應的列表分片獲取資料
引數:
name,redis的name
start,索引的起始位置
end,索引結束位置
llen(name)
name對應的list元素的個數
lrem(name, value, num)
在name對應的list中刪除指定的值
引數:
name, redis的name
value, 要刪除的值
num, num=0,刪除列表中所有的指定值;
num=2,從前到後,刪除2個;
num=-2,從後向前,刪除2個
自定義增量迭代
由於redis類庫中沒有提供對列表元素的增量迭代,如果想要迴圈name對應的列表的所有元素,那麼就需要:
- 獲取name對應的所有列表
- 迴圈列表
但是,如果列表非常大,那麼就有可能在第一步時就將程式的內容撐爆,所有有必要自定義一個增量迭代的功能:
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 # 只有拿完了才會去下一次while迴圈
print(conn.lrange('test',0,100))
for item in scan_list('test',5):
print(item)
通用操作
keys(pattern='*')
根據模型獲取 redis 的 name ——> 模糊匹配
更多:
KEYS * 匹配資料庫中所有 key 。
KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
KEYS h*llo 匹配 hllo 和 heeeeello 等。
KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo
delete(*names):根據 name 刪除 Redis 中的任意資料型別
exists(name):檢測 Redis 的 name 是否存在
expire(name ,time):為某個 redis 的某個 name 設定超時時間
rename(src, dst):重新命名
move(name, db):將redis的某個值移動到指定的db下
randomkey():隨機獲取一個redis的name(不刪除)
type(name):獲取name對應值的型別
管道
Redis 支援事務,但是是使用管道實現事務的,要麼都成功,要麼都失敗。
redis_pool.py
import redis
POOL = redis.ConnectionPool(host='127.0.0.1', port=6379,max_connections=100)
使用:
from redis import Redis
from redis_pool import POOL
conn = Redis(connection_pool=POOL)
pipe = conn.pipeline(transaction=True) # 開啟事務
pipe.multi()
pipe.set('name', 'xiaoyang')
pipe.set('age', '20')
pipe.execute() # 執行這句話才會真正去執行
三、Django中使用Redis
方式一:通用方式
建立redis_pool.py
import redis
# 生成一個池子物件最多能放100個連線
POOL = redis.ConnectionPool(host='127.0.0.1', port=6379,max_connections=100)
檢視函式中使用:
import redis
from django.shortcuts import render,HttpResponse
from redis_pool import POOL
def index(request):
conn = redis.Redis(connection_pool=POOL)
conn.hset('xiaoyang','name','xiaoyang')
return HttpResponse('設定成功')
def order(request):
conn = redis.Redis(connection_pool=POOL)
conn.hget('xiaoyang','name')
return HttpResponse('獲取成功')
方式二:django-redis
在 setting 中配置:
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache", # 指定快取使用的引擎
"LOCATION": "redis://127.0.0.1:6379", # 指定快取的路徑
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient", # 客戶端
"CONNECTION_POOL_KWARGS": {"max_connections": 100}, # 連線池
"PASSWORD": "123456", # 密碼
}
}
}
使用方式一:使用cache
from django.core.cache import cache
cache.set('name', 'xiaoyang')
使用方式二:直接使用conn物件
from django_redis import get_redis_connection
conn = get_redis_connection('default')
conn.set('name', 'xiaoyang')
ret = conn.get('name')
print(ret)