Python視訊學習(十四、Redis)
目錄
0. Redis基本介紹
- NoSQL的世界中沒有一種通用的語言,每種nosql資料庫都有自己的api和語法,以及擅長的業務場景
- NoSQL中的產品種類相當多:
- Mongodb
- Redis
- Hbase hadoop
- Cassandra hadoop
NoSQL和SQL資料庫的比較:
- 適用場景不同:sql資料庫適合用於關係特別複雜的資料查詢場景,nosql反之
- “事務”特性的支援:sql對事務的支援非常完善,而nosql基本不支援事務
兩者在不斷地取長補短,呈現融合趨勢
Redis簡介
- Redis是一個開源的使用ANSI C語言編寫、支援網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。從2010年3月15日起,Redis的開發工作由VMware主持。從2013年5月開始,Redis的開發由Pivotal贊助。
- Redis是 NoSQL技術陣營中的一員,它通過多種鍵值資料型別來適應不同場景下的儲存需求,藉助一些高層級的介面使用其可以勝任,如快取、佇列系統的不同角色
Redis特性:
Redis 與其他 key - value 快取產品有以下三個特點:
- Redis支援資料的持久化,可以將記憶體中的資料儲存在磁碟中,重啟的時候可以再次載入進行使用。
- Redis不僅僅支援簡單的key-value型別的資料,同時還提供list,set,zset,hash等資料結構的儲存。
- Redis支援資料的備份,即master-slave模式的資料備份。
Redis 優勢
- 效能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s 。
- 豐富的資料型別 – Redis支援二進位制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 資料型別操作。
- 原子 – Redis的所有操作都是原子性的,同時Redis還支援對幾個操作全並後的原子性執行。
- 豐富的特性 – Redis還支援 publish/subscribe, 通知, key 過期等等特性。
Redis應用場景
- 用來做快取(ehcache/memcached)——redis的所有資料是放在記憶體中的(記憶體資料庫)
- 可以在某些特定應用場景下替代傳統資料庫——比如社交類的應用
- 在一些大型系統中,巧妙地實現一些特定的功能:session共享、購物車
- 只要你有豐富的想象力,redis可以用在可以給你無限的驚喜…….
1. 安裝和配置
1.1 下載安裝Redis
$ wget http://download.redis.io/releases/redis-5.0.3.tar.gz
$ tar xzf redis-5.0.3.tar.gz
$ sudo mv redis-5.0.3 /usr/local
$ cd /usr/local/redis-5.0.3
$ sudo make test
$ sudo make install
根據README.md
中的說法,make install
安裝之後,可以在src
目錄下執行
./redis-server /path/to/redis.conf # 執行server,並且制定配置檔案
或者
% ./redis-server --port 9999 --replicaof 127.0.0.1 6379 # 不用配置檔案,直接指定引數
% ./redis-server /etc/redis/6379.conf --loglevel debug
但是make install
只會安裝二進位制檔案,並不會配置init 指令碼或者配置檔案到合適的位置。為了建立一個開發環境,Redis提供了
% cd utils
% ./install_server.sh
這個指令碼會詢問所有情況,並且配置各種deamon服務和配置檔案目錄、log目錄等等
之後就會有一個服務,名稱叫做redis_埠號
的,啟動即可
遇到的問題
- 沒有
cc
sudo apt install gcc
- jemalloc錯誤
make[1]: Entering directory '/home/yyfyifan/Downloads/redis-5.0.3/src'
CC Makefile.dep
CC adlist.o
In file included from adlist.c:34:0:
zmalloc.h:50:10: fatal error: jemalloc/jemalloc.h: No such file or directory
#include <jemalloc/jemalloc.h>
^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
Makefile:248: recipe for target 'adlist.o' failed
make[1]: *** [adlist.o] Error 1
make[1]: Leaving directory '/home/yyfyifan/Downloads/redis-5.0.3/src'
Makefile:6: recipe for target 'test' failed
make: *** [test] Error 2
解決方式:
make MALLOC=libc
- tcl版本
You need tcl 8.5 or newer in order to run the Redis test
解決方式:
sudo apt install tcl
或者(下面這個我試了,失敗了)
wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz
sudo tar xzvf tcl8.6.1-src.tar.gz -C /usr/local/
cd /usr/local/tcl8.6.1/unix/
sudo ./configure
sudo make
sudo make install
---------------------
原文:https://blog.csdn.net/luyee2010/article/details/18766911
1.2 配置資訊
sudo vi /etc/redis/redis.conf
-
繫結ip:如果需要遠端訪問,可將此⾏註釋,或繫結⼀個真實ip
bind 127.0.0.1
-
端⼝,預設為6379
port 6379
-
是否以守護程序運⾏
daemonize yes
- 如果以守護程序運⾏,則不會在命令⾏阻塞,類似於服務
- 如果以⾮守護程序運⾏,則當前終端被阻塞
- 設定為yes表示守護程序,設定為no表示⾮守護程序
-
資料⽂件
dbfilename dump.rdb
-
資料⽂件儲存路徑
dir /var/lib/redis
-
⽇志⽂件
logfile /var/log/redis/redis-server.log
-
資料庫,預設有16個
database 16
-
主從複製,類似於雙機備份。
slaveof
1.3 連線伺服器
redis-cli # 預設是連線到本地的6379埠,可以指定引數
執行測試命令:
PING
> PONG
資料庫沒有名稱,預設有16個,通過0-15來標識,連線redis預設選擇第一個資料庫,即0號資料庫
SELECT N # 切換到n號資料庫
2. 資料操作
2.1 資料型別
redis是key-value的資料結構,每條資料都是⼀個鍵值對。
鍵是字串,而值有5種類型:
- 字串string
- 雜湊hash(相當於字典)
- 列表list(每個元素都是字串)
- 集合set(每個元素都是字串)
- 有序集合zset(每個元素都是字串)
2.2 字串型別
字串型別是Redis中最為基礎的資料儲存型別,它在Redis中是二進位制安全的,這便意味著該型別可以接受任何格式的資料,如JPEG影象資料或Json物件描述資訊等。在Redis中字串型別的Value最多可以容納的資料長度是512M。
命令 | 說明 | 例子 |
---|---|---|
set key value |
設定鍵值對 | set iname itcast |
set key value EX 秒數 |
設定鍵值對的時候設定過期時間 | set abc haha EX 5 |
setex key seconds value |
設定鍵、值及過期時間,以秒為單位 | setex aa 3 aa |
mset key1 value1 key2 value2 ... |
設定多個鍵值 | mset a1 python a2 java a3 c |
append key value |
往已有的鍵對應值中追加字串 | append 'a1' 'haha' |
get key |
根據鍵獲取值 | get 'name' |
mget key1 key2 ... |
獲取多個值 | mget a1 a2 a3 |
2.3 鍵命令
命令 | 說明 | 例子 |
---|---|---|
keys pattern |
檢視所有符合pattern的鍵,支援萬用字元 | keys * |
exists 鍵 |
檢視這個鍵存在不存在,返回1代表存在 | exists a1 |
type 鍵 |
檢視這個鍵對應值的型別 | type a |
del key1 key2.. |
刪除對應的鍵和值 | del a1 a2 a3 |
expire key seconds |
設定鍵對應的過期時間,如果沒有設定,則一直存在 | expire a1 3 |
ttl key |
檢視剩餘存活時間 | ttl b2 |
2.4 hash型別
hash⽤於儲存物件,物件的結構為屬性、值,值的型別為string
新增修改命令 | 說明 | 例子 |
---|---|---|
hset key field value |
建立鍵值對,並且設定hash的單個屬性和值 | hset user name itheima (設定鍵 user的屬性name為itheima) |
hmset key field1 value1 field2 value2 ... |
建立鍵值對,並且設定多個屬性 | hmset u2 name itcast age 11 |
獲取命令 | 說明 | 例子 |
---|---|---|
hkeys key |
獲取指定key對應的所有fields | hkeys u2 |
hget key field |
獲取指定鍵的指定field對應的value | hget u2 name |
hmget key field1 field2 ... |
獲取指定鍵的多個指定field對應的value | hget u2 name age |
hvals key |
直接獲取該key的hash中所有fields的value | hvals u2 |
刪除命令 | 說明 | 例子 |
---|---|---|
del key |
刪除鍵 | |
hdel key field1 field2 ... |
刪除field和對應的value | hdel u2 age |
如果出現MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.錯誤。
那麼執行config set stop-writes-on-bgsave-error no
命令後,關閉配置項stop-writes-on-bgsave-error解決該問題
2.5 list型別
列表的元素型別為string
按照插⼊順序排序
插入命令 | 說明 | 例子 |
---|---|---|
lpush key value1 value2 ... |
從列表的左側插入資料 | lpush a1 0 1 |
rpush key value1 value2 .. |
從列表的右側插入資料 | rpush a1 0 1 |
linsert key before或after 現有元素 新元素 |
在指定元素的前或後插⼊新元素 | linsert a1 before b 3 在列表元素b的前面插入3 |
獲取命令 | 說明 | 例子 |
---|---|---|
lrange key start stop |
返回列表⾥指定範圍內的元素 | lrange a1 0 -1 |
- start、stop為元素的下標索引
- 索引從左側開始,第⼀個元素為0
- 索引可以是負數,表示從尾部開始計數,如-1表示最後⼀個元素
設定命令 | 說明 | 例子 |
---|---|---|
lset key index value |
設定 index 索引位置的值,索引從0開始,可以為負數 |
lset a 1 z |
刪除命令 | 說明 | 例子 |
---|---|---|
lrem key count value |
從某個方向開始,刪除count個value 。如果count=0, 則刪除所有出現的 value 如果count>0,那麼從左開始數count個刪除; 如果count<0, 那麼從右開始數-count個刪除 |
2.6 set型別
元素為string型別
元素具有唯⼀性,不重複
說明:對於集合沒有修改操作
新增命令 | 說明 |
---|---|
sadd key member1 member2 .. |
向key中新增集合值 |
獲取命令 | 說明 |
---|---|
smembers key |
返回所有的元素,無序,不保證和新增順序一致 |
刪除命令 | 說明 |
---|---|
srem key member1 ... |
刪除key集合中的指定元素 |
2.7 zset型別——有序集合
sorted set,有序集合
元素為string型別
元素具有唯⼀性,不重複
每個元素都會關聯⼀個double型別的score,表示權重,通過權重將元素從⼩到⼤排序
說明:沒有修改操作
新增命令 | 說明 | 例子 |
---|---|---|
zadd key score1 member1 score2 member2 .. |
向key中新增權重和值 | zadd a4 4 lisi 5 wangwu 6 zhaoliu 3 zhangsan |
獲取命令 | 說明 |
---|---|
zrange key start stop |
返回索引範圍內的值 |
zrangebyscore key min max |
返回score在min~max之間的值 |
zscore key member |
獲取member的score |
刪除命令 | 說明 |
---|---|
zrem key member1 member2 .. |
刪除key集合中的指定元素 |
zremrangebyscore key min max |
刪除score在min~max之間的元素 |
3. Python互動redis
3.1 安裝
pip install redis
3.2 使用
from redis import StrictRedis
sr = StrictRedis(host='localhost', port=6379, db=0)
# 可以簡寫為 sr = StrictRedis(),相當於本地的
# 根據不同的型別,擁有不同的例項⽅法可以調⽤,與前⾯學的redis命令對應,⽅法需要的引數與命令的引數⼀致
例子:
from redis import *
if __name__=="__main__":
try:
#建立StrictRedis物件,與redis伺服器建⽴連線
sr=StrictRedis()
#新增鍵name,值為itheima, 成功返回True,否則False
result=sr.set('name','itheima')
print(result)
#輸出鍵的值,如果鍵不存在則返回None
result = sr.get('name')
# 刪除鍵,返回刪除成功的個數
result = sr.delete('name')
print(result) # 1
# 獲取所有的鍵,不傳引數代表 keys *
result=sr.keys()
except Exception as e:
print(e)
3.3 Djangon中用Redis儲存Session
之前django的session預設是存在的資料庫裡面一張session表中,我們也可以把session儲存在redis裡面,訪問速度更快。
- 安裝包:
pip install django-redis-sessions
- 配置使用Redis來放置Session資訊
在settings.py
中,最下面新增這些
SESSION_ENGINE = 'redis_sessions.session' # 固定的
SESSION_REDIS_HOST = 'localhost' # Redis資料庫 ip
SESSION_REDIS_PORT = 6379 # Redis埠
SESSION_REDIS_DB = 2 # 第幾個資料庫
SESSION_REDIS_PASSWORD = '' # 沒有就空
SESSION_REDIS_PREFIX = 'session' # 儲存在Redis中的key的字首
- 測試
def session_set(request):
request.session['name']='itheima'
return HttpResponse('ok')
def session_get(request):
name=request.session['name']
return HttpResponse(name)
4. Redis配置主從
- ⼀個master可以擁有多個slave,⼀個slave⼜可以擁有多個slave,如此下去,形成了強⼤的多級伺服器叢集架構
- master用來寫資料,slave用來讀資料,經統計:網站的讀寫比率是10:1
- 通過主從配置可以實現讀寫分離
新版本的Redis, slave這個詞改成了 replica
配置主從
步驟:
- 配置主的ip和port
- 啟動主,並且指定配置檔案
- 配置從的ip和port
- 配置從的
replicaof
用來指定主例項的位置 - 啟動從,並且指定從的配置檔案
主例項配置:
- bind和port
bind 192.168.26.128
port 6379
-
不要配置
replicaof
-
啟動服務
redis-server /path/to/config
從例項配置
- 設定port——不要和主的相同
bind 192.168.26.128
port 6380
- 配置
replicaof
指向主例項
replicaof 192.168.26.128 6379
- 啟動例項並且指定這個配置檔案
redis-server /path/to/slaveconfig
測試主從
redis-cli -h IP info # 檢視所有該redis資訊(包括主從關係)
redis-cli -h IP info REPLICATION # 檢視主從關係
在主例項上連線,建立新的內容,在從伺服器上檢視
不能寫入從,從只能用來讀取
5. Redis叢集
- 如果同時的訪問量過大(1000w),主服務肯定就會掛掉,資料服務就掛掉了或者發生自然災難。
- 叢集相當於是網路中的多臺節點互相連線,並以單一系統的模式加以管理。一個客戶與叢集相互作用時,叢集像是一個獨立的伺服器。叢集配置是用於提高可用性和可縮放性。
- Redis叢集有2類:軟體層面和硬體層面
- 軟體層面:只有一臺電腦,在這一臺電腦上啟動了多個redis服務。
- 硬體層面:存在多臺實體的電腦,每臺電腦上都啟動了一個redis或者多個redis服務。
- 軟體層面:只有一臺電腦,在這一臺電腦上啟動了多個redis服務。
5.1 搭建Redis叢集
在2臺機器上啟動6個服務
現在使用2個機器,每個機器上面執行3個redis服務來搭建叢集。
- 第一臺機器IP為
172.16.179.130
, 分別建立3個配置檔案:
# 7000.conf
port 7000
bind 172.16.179.130
daemonize yes
pidfile 7000.pid
cluster-enabled yes
cluster-config-file 7000_node.conf
cluster-node-timeout 15000
appendonly yes
# 7001.conf
port 7001
bind 172.16.179.130
daemonize yes
pidfile 7001.pid
cluster-enabled yes
cluster-config-file 7001_node.conf
cluster-node-timeout 15000
appendonly yes
# 7002.conf
port 7002
bind 172.16.179.130
daemonize yes
pidfile 7002.pid
cluster-enabled yes
cluster-config-file 7002_node.conf
cluster-node-timeout 15000
appendonly yes
總結:三個⽂件的配置區別在port、pidfile、cluster-config-file三項
然後啟動三個服務:
redis-server 7000.conf
redis-server 7001.conf
redis-server 7002.conf
- 第二臺機器IP為
172.16.179.131
,也分別建立3個配置檔案並且啟動服務:
# 7003.conf
port 7003
bind 172.16.179.131
daemonize yes
pidfile 7003.pid
cluster-enabled yes
cluster-config-file 7003_node.conf
cluster-node-timeout 15000
appendonly yes
# 7004.conf
port 7004
bind 172.16.179.131
daemonize yes
pidfile 7004.pid
cluster-enabled yes
cluster-config-file 7004_node.conf
cluster-node-timeout 15000
appendonly yes
# 7005.conf
port 7005
bind 172.16.179.131
daemonize yes
pidfile 7005.pid
cluster-enabled yes
cluster-config-file 7005_node.conf
cluster-node-timeout 15000
appendonly yes
redis-server 7003.conf
redis-server 7004.conf
redis-server 7005.conf
建立叢集
redis的安裝包中包含了redis-trib.rb
,⽤於建立叢集
6個服務最後會成為3個節點,每個節點都是一個主一個從。 每個主/從節點會分配到一個 槽的區間, redis叢集儲存內容是儲存在16384 個slot中,所以會把這些槽分配給各個節點,每個節點儲存一部分。
具體步驟省略,因為我嘗試的安裝redis之後找不到這個命令
5.2 資料驗證
連線上任何一個地址,然後寫入資料,它會根據寫入的key來自動跳轉到對應的主node上,然後寫入。
在哪個伺服器上寫資料:CRC16
- redis cluster在設計的時候,就考慮到了去中⼼化,去中介軟體,也就是說,叢集中 的每個節點都是平等的關係,都是對等的,每個節點都儲存各⾃的資料和整個集 群的狀態。每個節點都和其他所有節點連線,⽽且這些連線保持活躍,這樣就保 證了我們只需要連線叢集中的任意⼀個節點,就可以獲取到其他節點的資料
- Redis叢集沒有並使⽤傳統的⼀致性雜湊來分配資料,⽽是採⽤另外⼀種叫做**雜湊 槽 (hash slot)**的⽅式來分配的。redis cluster 預設分配了 16384 個slot,當我們 set⼀個key 時,會⽤CRC16演算法來取模得到所屬的slot,然後將這個key 分到哈 希槽區間的節點上,具體演算法就是:CRC16(key) % 16384。所以我們在測試的 時候看到set 和 get 的時候,直接跳轉到了7000端⼝的節點
- Redis 叢集會把資料存在⼀個 master 節點,然後在這個 master 和其對應的salve 之間進⾏資料同步。當讀取資料時,也根據⼀致性雜湊演算法到對應的 master 節 點獲取資料。只有當⼀個master 掛掉之後,才會啟動⼀個對應的 salve 節點,充 當 master
- 需要注意的是:必須要3個或以上的主節點,否則在建立叢集時會失敗,並且當存 活的主節點數⼩於總節點數的⼀半時,整個叢集就⽆法提供服務了
5.3 Python和Redis叢集的互動
安裝包
pip install redis-py-cluster
示例程式碼:
from rediscluster import StrictRedisCluster
if __name__ == '__main__':
try:
# 構建所有的節點,Redis會使⽤CRC16演算法,將鍵和值寫到某個節點上
startup_nodes = [
{'host': '192.168.26.128', 'port': '7000'},
{'host': '192.168.26.130', 'port': '7003'},
{'host': '192.168.26.128', 'port': '7001'},
]
# 構建StrictRedisCluster物件
src=StrictRedisCluster(startup_nodes=startup_nodes,decode_responses=True)
# 設定鍵為name、值為itheima的資料
result=src.set('name','itheima')
print(result)
# 獲取鍵為name
name = src.get('name')
print(name)
except Exception as e:
print(e)