目錄
Redis資料庫快速入門
一、Redis資料庫
介紹:
Redis:非關係型快取資料庫
-
nosql:非關係型資料庫
- 沒有表,沒有表與表之間的關係,更不存在外來鍵
- 儲存資料的形式為key:values的形式
- c語言寫的服務(監聽埠),用來儲存資料的,資料是儲存在記憶體中,取值,放值速度非常快, 10w qps
-
快取資料庫:
- 資料儲存在記憶體中
- 大部分時間用於快取,也可以長久儲存資料
-
redis速度為什麼這麼快:
- 純記憶體操作
- 網路模型使用的IO多路複用(可以處理的請求更多)
- 6.x版本之前,單程式,單執行緒,不存在程式執行緒之間切換,更少消耗資源
1、redis的安裝與執行
版本選擇:
- mac:原始碼編譯安裝
- linux:原始碼編譯安裝
- windows:
- redis沒有windows的版本,只有微軟基於原始碼改動,編譯的安裝包(用法一樣)
- 3.x版本 https://github.com/microsoftarchive/redis/releases
- 最新5.x版本 https://github.com/tporadowski/redis/releases/
安裝:
redis需要了解的目錄結構:
- redis-server :服務端啟動檔案
- redis-cli:客服端啟動檔案
- redis.windows-service.conf:預設使用的配置檔案
- bind 127.0.0.1 :服務端跑在的地址
- port 6379 :佔用的埠號
啟動redis:
- 方式一:將服務端新增至系統服務(電腦執行自動啟動)
* - 方式二:cmd終端使用命令啟動
- redis-server 指定配置檔案 # 如果不指定,會預設
客服端連結redis:
-
cmd終端使用命令
-
方式一:redis-cli 預設連結本地的6379埠
-
方式二:redis-cli -h 地址 -p 埠
-
2、RESP圖形化操作檔案
可以使用軟體:
Redis Desktop Manager :開源的,原來免費,後來收費了 推薦用(mac,win,linux 都有)
-Qt5 qt是個平臺,專門用來做圖形化介面的
-可以使用c++寫
-可以使用python寫 pyqt5 使用python寫圖形化介面 (少量公司再用)
-resp-2022.1.0.0.exe 一路下一步,安裝完啟動起來
-Redis Client 小眾
RESP操作redis:
二、pycharm操作redis
安裝模組:
使用pycharm操作redis,pycharm相當於客戶端,輸入redis命令即可對資料庫進行操作
# 下載模組:
pip install redis
# 補充:django 中操作mysql,沒有連線池的,一個請求就是一個mysql連線
-可能會有問題,併發數過高,導致mysql連線數過高,影響mysql效能
-使用django連線池:https://blog.51cto.com/liangdongchang/5140039
1、Redis普通連線和連線池
普通連結:
普通連結是指,直接操作redis,每一次操作都會建立一條連結
# 匯入模組
from redis import Redis
# 例項化物件(後方引數填寫連結的地址和埠,還可以填寫其他引數)
conn = Redis(host='127.0.0.1', port=6379)
# 向redis中存放一個資料
conn.set('name', 'kangkang')
# 從redis中取出存放的資料(二進位制格式)
print(conn.get('name'))
# 操作完成,手動關閉,不然會一直佔用一條連結
conn.close()
連線池連線:
拿到一個Redis例項的連線池,避免每次建立、釋放連線的開銷,節省了每次連線用的時間,文中設定了最大10個。
POOL.py
# 1、使用單例模式(保證每次使用的都是同一個例項物件),設定連線池最大為10個
import redis
POOL = redis.ConnectionPool(
# 最大連結
max_connections=10,
# 指定服務端地址
host='127.0.0.1',
prot=6379
)
my_redis.py
# 匯入redis
from redis import Redis
# 匯入執行緒模組(模仿多執行緒併發)
from threading import Thread
# 匯入自己建立的單例
from script.pool import POOL
# 寫一個函式,在內部操作redis
def task():
# 以後生成的物件都是POLL這一個例項化的物件
conn = Redis(connection_pool=POOL)
conn.set('name', 'kangkang')
print(conn.get('name'))
if __name__ == '__main__':
for i in range(100):
t = Thread(target=task)
t.start()
2、Redis資料型別
介紹:
redis 是key-value形式儲存
redis 資料放在記憶體中,如果斷電,資料丟失---》需要有持久化的方案
型別 | 介紹 |
---|---|
字串(string) | 用的最多,做快取;做計數器 |
列表(list) | 常用於訊息佇列 |
字典(hash) | 快取 |
集合(set) | 去重 |
有序集合(zset) | 排行榜 |
2、1.String型別
# 1、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)
等同於set('name','kangkang',nx=True)
# 3、setex(name,time,values)
等同於set('name',10,'kangkang')
# 4、psetex(name,time_ms,values)
conn.psetex('name',3000,'kangkang')
# 5、mset(*args,**kwargs)
可以批次存入資料
conn.mset({'name':'kangkang','age':18})
# 6、get(name)
取值(單個)
coon.get('name')
# 7、mget(keys, *args)
批次取值(可以是列表)
coon.mget('name','age')
coon.mget(['name','age'])
# 8、getset(name, value)
放置新的值進入(可以使用變數接收被替換的值)
res = coon.getset('name','jason')
# 9、getrange(key, start, end)
按照指定key對應值的索引位置取值(按位元組取值)
res = coon.gettrange('name',0 ,3)
# 10、settrange(name, offset, value)
按照索引位置替換指定key對應的值(按照位元組)
coon.settrange('name',3,'bbb')
---- 位元位---操作----
# 11 setbit(name, offset, value)
# 12 getbit(name, offset)
# 13 bitcount(key, start=None, end=None)
---- 位元位---操作-----
# 14、bitop(operation, dest, *keys)
獲取多個值,並將值做位運算,將最後的結果儲存至新的name對應的值
# 15、strlen(name)
獲取指定key對應值的位數(按位元組)
res = coon.strlen('name')
# 16、incr(self, name, amount=1)
自增(預設自增:1,不支援含有浮點型別)
conn.incr('age')
# 17、incrbyfloat(self, name, amount=1.0)
自增(支援小數)
# 18、decr(self, name, amount=1)
自減
# 19、append(key, value)
在指定key對應值的後面新增指定字元
conn.append('name','NB')
2、2.List型別
from redis import Redis
conn = Redis(host='127.0.0.1', port=6379)
# 1、lpush(name, values)
# 鍵為key,值為list(引數位置在前生成資料的索引位置就在後)
conn.lpush('gender', 'male', 'female')
# 2、rpush(name, values)
# 鍵為key,值為list(引數位置在前生成資料的索引位置就在前)
conn.rpush('hobby', 'read', 'run')
# 3、lpushx(name, value)
# 向列表插入一個值(有對應的key就插入到列表的頭部,沒有就不操作)
conn.lpushx('gender', 'female')
# 4、rpushx(name, value)
# 向列表插入一個值(有對應的key就插入到列表的尾部部,沒有就不操作)
conn.rpushx('hobby', 'ball')
# 5、llen(name)
# 判斷列表內有多少個資料
print(conn.llen('hobby'))
# 6、linsert(name, where, refvalue, value))
# name:插入到哪個列表
# where:插入到指定值的前或後before:前/after:後
# refavalue:插入到哪個值
# value:插入的值
# 向列表內插入資料
conn.linsert('hobby', 'after', 'run', 'go')
# 7、lset
# 向指定的索引位置插入一個值
conn.lset('hobby', 1, 'sleep')
# 8、lrem
# 刪除指定的值,可以指定刪除的數量,填 0 全部刪除,負數從後面刪除
conn.lrem('hobby', 0, 'aaaa')
# 9、lpop(name)
# 從頭部彈出一個值,可以接收
res = conn.lpop('hobby')
print(res)
# 10、rpop(name)
# 從尾部彈出一個值,可以接收
res = conn.rpop('hobby')
print(res)
# 11、lindex(name, index)
# 按照索引位置取值
res = conn.lindex('hobby', 1)
print(res)
# 12、lrange(name, start, end)
# 按照索引位置,範圍取值,第二個引數填負數取全部
res = conn.lrange('hobby', 0, -1)
print(res)
# 13、ltrim(name, start, end)
# 修剪,留下索引位置內的資料
res = conn.ltrim('hobby', 1, 2)
print()
# 14、rpoplpush(src, dst)
# 提供兩個列表,將第一個列表的值被彈出,加入到第二個列表內
conn.lpush('gender', 'male')
conn.rpoplpush('gender', 'hobby')
# 15、blpop(keys, timeout)
# 可做訊息佇列,彈出資料(從左向右)
res = conn.blpop('hobby')
print(res)
# 16、brpop(keys, timeout)
# 可做訊息佇列,彈出資料(從右向左)
res = conn.brpop('hobby')
print(res)
# 17、brpoplpush(src, dst, timeout=0)
# 將彈出的資料加入到兩一個列表中
res = conn.brpoplpush('hobby','gender')
print(res)
conn.close()
2、3.Hash型別
import redis
conn = redis.Redis()
# 1、hset(name, key, value)
# 設定一個key,value值為字典
conn.hset('userinfo','name','lqz')
# 這種方法可以一次寫入多個鍵值對
conn.hset('userinfo',mapping={'age':19,'hobby':'籃球'})
# 2、hmset(name, mapping)
# 批次設定,被棄用了,以後都使用hset
conn.hmset('userinfo2',{'age':19,'hobby':'籃球'})
# 3、hget(name,key)
# 取值
res = conn.hget('userinfo', 'name')
print(res)
# 4、hmget(name, keys, *args)
# 批次取值
res = conn.hmget('userinfo', ['name', 'age'])
# 第二種寫法
res = conn.hmget('userinfo', 'name', 'age')
print(res)
# 5、hgetall(name)
# 一次性取出所有的值(慎用,資料量龐大的話會引起司機、當機)
res=conn.hgetall('userinfo')
print(res)
# 6、hlen(name)
# 獲取鍵值對的數量
res=conn.hlen('userinfo')
print(res)
# 7、hkeys(name)
# 一次性獲取所有key值
res=conn.hkeys('userinfo')
print(res)
# 8、hvals(name)
# 一次性獲取所有value值
res=conn.hvals('userinfo')
print(res)
# 9、hexists(name, key)
# 判斷value值是否存在,返回1/0
res = conn.hexists('userinfo', 'name')
res = conn.hexists('userinfo', 'name1')
print(res)
# 10、hdel(name,*keys)
# 刪除對應的value值
res = conn.hdel('userinfo', 'age')
print(res)
# 11、hincrby(name, key, amount=1)
# 指定欄位自增,預設自增1
conn.hincrby('userinfo', 'age', 2)
# 12、hincrbyfloat(name, key, amount=1.0)
# 自增,支援小數
# 13、hgetall(name)
# 一次性取出所有value的鍵值對
# 插入一批資料
for i in range(1000):
conn.hset('hash_test','id_%s'%i,'雞蛋_%s號'%i)
res=conn.hgetall('hash_test') # 可以,但是不好,一次性拿出,可能佔很大記憶體
print(res)
# 14、hscan(name, cursor=0, match=None, count=None)
# 按照遊標位置取值
res = conn.hscan('hash_test', cursor=0, count=5)
print(len(res[1])) #(數字,拿出來的10條資料) 數字是下一個遊標位置
# 15、hscan_iter(name, match=None, count=None)
# 類似生成器,一次只拿出指定數量的值
res = conn.hscan_iter('hash_test', count=10)
print(res) # generator 只要函式中有yield關鍵字,這個函式執行的結果就是生成器 ,生成器就是迭代器,可以被for迴圈
for i in res:
print(i)
conn.close()
4、通用操作
import redis
conn = redis.Redis()
# 1、delete(*names)
# 刪除指定的key,一次刪除多個
conn.delete('name', 'userinfo2')
conn.delete(['name', 'userinfo2']) # 不能用它
conn.delete(*['name', 'userinfo2']) # 可以用它,打散
# 2、exists(name)
# 判斷redis中是否存在指定的key(返回 0/1)
res=conn.exists('userinfo')
print(res)
# 3、keys(pattern='*')
# 查詢value的key值中是否存在指定的key,返回對應的value(支援簡單的正則)
res=conn.keys('w?e') # ?表示一個字元, * 表示多個字元
print(res)
# 4、expire(name ,time)
# 設定過期時間
conn.expire('userinfo',3)
# 5、rename(src, dst)
# 重新命名
conn.rename('hobby','hobby111')
# 6、move(name, db)
# 更改儲存資料的庫
conn.move('hobby111',8)
# 7、randomkey()
# 隨機獲得一個key
res = conn.randomkey()
print(res)
# 8、type(name)
# 判斷資料的型別
print(conn.type('userinfo'))
print(conn.type('age'))
conn.close()
3、Redis管道
什麼是管道:
管道是指,將多條redis操作放在管道內同時執行,管道也是一種事務的操作,可以作用於敏感,重要的資料
ridis支援事務嗎:
redis的事務基於管道,只有單例項才支援事務
ridis管道的使用:
# 引入redis
import redis
# 例項化redis物件
conn = redis.Redis()
# 例項化管道
p = conn.pipeline(transaction=True)
# 開啟管道(類似於開啟事務)
p.multi()
# 模擬張三給李四100元
p.decr('zhangsan', 100)
# 模擬李四賬戶增加100元
p.incr('lisi', 100)
# 啟動管道(類似於提交事務)
p.execute()
# 關閉
p.close()
三、Django操作Redis
1、自定義包方案
這種方案所有的框架都可以使用
- 1、第一步:建立一個pool.py檔案(匯入rides,並例項化物件,生成連線池)
import Redis
# 例項化物件,設定連線池最大數量為100
POOL = Redis.CoonectionPool(max_connections=100)
- 2、第二步:在以後需要使用的地方直接匯入使用即可
from pool import POOL
from redis import Redis
conn = Redis(connections=POOL)
conn.set('name','kangkang')
res = conn.get('name')
2、將Redis設定為Django快取[推薦使用]
需要安裝模組,配置settings檔案,以後直接作為Django內建快取使用
- 安裝模組:
pip install django-redis
- settings.py 中配置:
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": "123", # 密碼,沒有的話不用設定
}
}
}
- 在需要使用的地方直接使用即可(但是隻能支援記憶體的操作)
在使用redis的地方:cache.set('count', res+1) # 可以存入任何型別的資料
# 底層做了pickle序列化
3、使用第三方模組
直接使用django-redis模組
from django_redis import get_redis_connection
def test_redis(request):
conn=get_redis_connection()
print(conn.get('count'))
return JsonResponse()