redis 第二節 redis 入門使用
Redis是一個開源(BSD許可),記憶體資料結構儲存,用作資料庫,快取和訊息代理。它支援資料結構,如 字串,雜湊,列表,集合,帶有範圍查詢的排序集,點陣圖,超級日誌和帶有半徑查詢的地理空間索引。Redis具有內建複製,Lua指令碼,LRU驅逐,事務和不同級別的磁碟永續性,並通過Redis Sentinel提供高可用性和Redis Cluster自動分割槽。
你可以 對這些型別執行原子操作,例如附加到字串 ; 遞增雜湊值 ; 將元素推送到列表中 ; 計算集合交集, 並集和差異 ; 或者在排序集中獲得排名最高的成員。
為了實現其出色的效能,Redis使用 記憶體資料集
Redis還支援簡單到設定的主從非同步複製,具有非常快速的非阻塞第一次同步,自動重新連線以及在網路分割上的部分重新同步。
Redis 安裝
windows 安裝
官方沒有windows版本的支援,但是微軟維護這一個windows 64位的redis版本,程式碼託管在github上,可以使用該地址進行下載,https://github.com/MicrosoftArchive/redis/releases
按照需要進行下載檔案,解壓後redis對應的服務程式為redis-server.exe,配置檔案為 redis.windows.conf,啟動完成後,使用redis-cli.ext -h127.0.0.1 -p6379 來對redis資料庫進行操作。
Linux 安裝
到官網下載redis的安裝包 Redis官網 下載對應的linux的作業系統的安裝包(分為穩定,不穩定和測試三個版本)。
具體操作如下:
# 下載原始碼包
wget http://download.redis.io/releases/redis-4.0.11.tar.gz
# 解壓
tar xzf redis-4.0.11.tar.gz
# 切換工作目錄
cd redis-4.0.11
# make 編譯
make
# 編譯好的二進位制檔案在src目錄下。
# 可以自行拷貝進行使用,也可以使用make install命令安裝。
# 如果執行make install 預設檔案被放到/usr/local/bin/下,也可以使用 PREFIX=/to/path 引數來指定存放位置
make install PREFIX=/usr/local/
Redis 配置
redis的配置檔案位於redis目錄下,檔名為redis.conf,配置檔案的修改可以通過修改配置檔案重啟redis來使配置檔案生效,或者使用CONFIG SET|GET 命令來進行動態配置。
Redis 資料持久化
Redis是個支援持久化的記憶體資料庫,redis需要經常將記憶體中的資料同步到磁碟來保證持久化。
RDB 方式
RDB 方式為預設的快照方式。
配置
# 該配置一般為預設配置
save 900 1 #在900秒(15分鐘)之後,如果至少有1個key發生變化,則dump記憶體快照。
save 300 10 #在300秒(5分鐘)之後,如果至少有10個key發生變化,則dump記憶體快照。
save 60 10000 #在60秒(1分鐘)之後,如果至少有10000個key發生變化,則dump記憶體快照。
工作原理
RDB方式持久化命令如下:
命令 | 說明 |
---|---|
SAVE | 執行後會阻塞Redis伺服器程序,直到RDB檔案建立完畢,在阻塞過程過程中伺服器不處理任何來自外界的請求無論讀還是寫(阻塞所有請求)。 |
BGSAVE | 會產生一個子程序,由此子程序來處理建立RDB檔案任務,而伺服器的父程序繼續響應外部請求。 |
BGREWRITEAOF | 用於非同步執行一個 AOF(AppendOnly File) 檔案重寫操作。重寫會建立一個當前 AOF 檔案的體積優化版本。 即使 Bgrewriteaof 執行失敗,也不會有任何資料丟失,因為舊的 AOF 檔案在 Bgrewriteaof 成功之前不會被修改。 (注意: 從 Redis 2.4 開始, AOF 重寫由 Redis 自行觸發, BGREWRITEAOF 僅僅用於手動觸發重寫操作。 ) |
LASTSAVE | 返回最近一次 Redis 成功將資料儲存到磁碟上的時間,以 UNIX 時間戳格式表示。 |
BGSAVE
在執行過程中不會阻塞請求,但是不是任何請求都可以執行,在伺服器執行BGSAVE
期間,對於執行SAVE
、BGSAVE
和BGREWRITEAOF
這三個命令會有所有不同。
在BGSAVE執行期間 | |
---|---|
執行SAVE命令 | 會被伺服器拒絕,伺服器禁止SAVE命令和BGSAVE同時執行,因為不可能讓兩個命令去呼叫同一函式然後去操作同一個RDB檔案。 |
執行BGSAVE命令 | 會被伺服器拒絕,因為已經有一個在進行了,沒必要再允許一個 。 |
執行BGREWRITEAOF命令 | 會被延遲執行,BGSAVE子程序完成後,才會執行BGREWRITEAOF命令 。 |
在BGSAVE執行期間 | |
---|---|
執行BGSAVE命令 | 會被拒絕,這兩個命令沒有衝突的地方,只是同時執行會產生大量磁碟寫操作,會影響效能,所以這是一個規則上的拒絕,不是一個技術上的拒絕 |
BGSAVE 工作原理
-
Redis使用fork函式複製一份當前程序(父程序)的副本(子程序)。
-
父程序繼續接收並處理客戶端發來的命令,而子程序開始將記憶體中的資料寫入硬碟中的臨時檔案。
-
當子程序寫入完所有資料後會用該臨時檔案替換舊的RDB檔案,至此一次快照操作完成。
檢視rds檔案配置
通過使用CONFIG GET
命令可以檢視持久化資料儲存的位置。
> config get dir
1) "dir"
2) "E:\\redis\\redis3.0"
> config get dbfilename
1) "dbfilename"
2) "dump.rdb"
RDB方式優點
-
RDB是個非常緊湊的檔案,儲存了redis在某個時間點上的資料集,使得我們可以通過定時備份RDB檔案來實現Redis資料庫備份和災難恢復,也可以將其傳送到其他的資料中心用於儲存。
-
RDB可以最大化redis的效能,執行RDB持久化時只需要fork一個子程序,並由子程序進行持久化工作,父程序不需要處理任何磁碟I/O操作。
-
RDB在恢復大資料集時比AOF要快,啟動效率要高許多。
-
RDB檔案是經過壓縮(可以配置rdbcompression引數以禁用壓縮節省CPU佔用)的二進位制格式,所以佔用的空間會小於記憶體中的資料大小,更加利於傳輸。
RDB方式缺點
-
每次快照持久化都是將記憶體資料完整寫入到磁碟一次,並不是增量的只同步增資料。如果資料量大的話,而且寫操作比較多,必然會引起大量的磁碟io操作,可能會嚴重影響效能。
-
快照方式是在一定間隔時間做一次的,所以如果redis意外down掉的話,就會丟失最後一次快照後的所有修改,有一些資料丟失的風險。
-
client的
save
或者bgsave
命令通知redis做一次快照持久化不推薦。
原因:save操作是在主執行緒中儲存快照的,由於redis是用一個主執行緒來處理所有 client的請求,這種方式會阻塞所有client請求。所以不推薦使用。
RDB 方式注意事項
Redis模式會執行16個數據庫(編號為0---15),在執行儲存的過程中無論是SAVE
觸發還是BGSAVE
觸發,都是會把所有非空
資料庫進行儲存的。
Append-only file(縮寫aof)的方式
預設AOF 方式是關閉的。
RDB方式如果redis 服務意外停止執行後,會將最新寫入的資料丟失,在某些嚴格要求的專案中不是一個可行的方案。此時AOF可以解決這個問題,AOF 方式是在redis 1.1 版本中可用。
AOF 方式是在寫入記憶體資料的同時將操作命令儲存到日誌檔案中。 當你重新啟動redis 服務時,它將重新根據AOF以重建狀態。這種方式類似於傳統資料庫伺服器的事務日誌 。
如果遇到在追加日誌的時候遇到意外,可以使用redis-check-aof工具進行日誌修復。
因為採用了追加方式,所以AOF會越來越大(這一點又和傳統資料庫不一樣,傳統資料庫事務日誌檔案都比較小),因此redis有另外一個機制就是AOF檔案重寫,當AOF檔案達到一個設定的閾值後,會自動啟動AOF檔案壓縮,只保留可以恢復資料的最小指令集。
配置
# 在配置檔案中開啟AOF
appendonly yes
# aof方式檔名
appendfilename "appendonly.aof"
# 每次執行寫入都會執行同步,最安全也最慢,執行write()和fsync()系統呼叫。
# appendfsync always
# 每秒執行一次同步,預設,執行write()和fsync()系統呼叫。
appendfsync everysec
# 不主動進行同步操作,而是完全交由作業系統來做(即每30秒一次),最快也最不安全,只執行write()。
# appendfsync no
AOF 持久化原理
-
當AOF 持久化開啟後,對資料庫進行一次更新操作後,更新命令會被追加到
aof_buf
緩衝區的末尾,然後緩衝區寫入到AOF 檔案。 -
AOF檔案中記錄的內容就是對資料更新操作的指令。這個檔案本身就是以文字來記錄的。
對redis
進行了如下操作:
> set 40kuai 40
OK
> get 40kuai 40
(error) ERR wrong number of arguments for 'get' command
> get 40kuai
"40"
> del 40kuai
(integer) 1
下面我們來檢視下appendonly.aof
檔案的內容:
*2
$6
SELECT
$1
0
*3
$3
set
$6
40kuai
$2
40
*2
$3
del
$6
40kuai
分別解釋下各個欄位的含義:
字元 | 含義 |
---|---|
*2 | 表示2個引數 |
$6 | 第一個引數長度為6 |
SELECT | 第一個引數 |
$1 | 第二個引數的長度為1 |
0 | 第二個引數 |
注意:這裡可以看出 appendonly.aof
檔案中記錄的都是對資料進行操作的命令,對於使用者使用GET
進行查詢的操作並沒有記錄。
AOF 重寫實現原理
因為AOF持久化是通過記錄命令的方式來儲存資料庫狀態的,隨著時間的推移AOF檔案肯定會逐漸增大,如果不加以控制會對AOF持久化效能以及資料恢復造成影響。
以一個列表為例來說明重寫的意義:
> rpush list a b
(integer) 2
> rpush list c
(integer) 3
> lrange list 0 1
1) "a"
2) "b"
根據AOF的原理,上面的操作需要將2條命令追加到appendonly.aof
檔案當中,其實我們看到list
最後的狀態是值a,b,c
。當使用appendonly.aof
檔案進行恢復時,要實現最後的狀態,需要追加2 條命令,所以在大量記憶體讀寫的業務裡AOF檔案增長的很快。為了解決這個問題,Redis提供了AOF重寫功能。
AOF重寫就是建立一個新的AOF檔案來替換現有的AOF檔案,實際上AOF重寫並不對現有的舊AOF檔案進行操作。當進行重寫的時候直接從資料庫裡去獲取list的最新狀態,然後在新的AOF檔案中直接寫一條rpushlist B C D E F命令,從而避免寫5條的操作,這樣AOF檔案的增長速度就會降低,同時容量也不會特別大。
AOF重寫程式aof_rewrite函式去完成建立新的AOF檔案的任務,但是該函式並不會由Redis主程序去直接呼叫,而是使用子程序後臺去執行(BGREWRITEAOF,該命令其實就是執行aof_rewrite,只不過是由子程序去呼叫的),這時主程序就會不被阻塞,那麼就可以在執行重寫的過程中父程序可以繼續對外提供響應。整個過程如下:
-
當重寫被觸發時父程序呼叫一個函式,該函式建立一個子程序用於執行
BGREWRITEAOF
,該子程序建立一個臨時檔案,然後父程序繼續對外提供讀寫服務。 -
子程序遍歷資料庫,將每個鍵值的最新狀態輸出到臨時檔案中,在BGREWRITEAOF過程中,父程序把所有對資料庫的更新命令同時寫入到AOF緩衝區和AOF重寫緩衝區(aof_rewrite_buf_blocks),AOF緩衝區(aof_buf)會繼續同步到現有AOF檔案中(一般情況下在AOF重寫期間不建議把AOF緩衝區的內容同步到現有的AOF檔案中,這會降低效能,預設為NO)。
-
AOF重寫完成後子程序通知父程序,父程序呼叫訊號處理函式。
-
訊號處理函式會阻塞父程序對外提供讀寫操作(時間很短,不阻塞就又會出現資料不一致的情況),然後將AOF重寫緩衝區的內容寫入到新的AOF檔案中,最後用新的AOF檔案替換現有AOF檔案(更名操作)。
# yes : 在日誌重寫時,不進行命令追加操作,而只是將其放在緩衝區裡,避免與命令的追加造成DISK IO上的衝突。
# no : 在日誌重寫時,命令追加操作照常進行。
no-appendfsync-on-rewrite no
# 當目前的AOF檔案大小超過上一次重寫時的AOF檔案大小的百分之多少時會再次進行重寫,如果之前沒有重寫過,則以啟動時的AOF檔案大小為依據
auto-aof-rewrite-percentage 100
# 允許重寫的最小AOF檔案大小
auto-aof-rewrite-min-size 64mb
AOF 方式優點
-
該機制可以帶來更高的資料安全性,即資料永續性。
-
由於該機制對日誌檔案的寫入操作採用的是append模式,因此在寫入過程中即使出現宕機現象,也不會破壞日誌檔案中已經存在的內容。然而如果我們本次操作只是寫入了一半資料就出現了系統崩潰問題,不用擔心,在Redis下一次啟動之前,我們可以通過redis-check-aof工具來幫助我們解決資料一致性的問題。
-
如果日誌過大,Redis可以自動啟用rewrite機制。即Redis以append模式不斷的將修改資料寫入到老的磁碟檔案中,同時Redis還會建立一個新的檔案用於記錄此期間有哪些修改命令被執行。因此在進行rewrite切換時可以更好的保證資料安全性。
-
AOF包含一個格式清晰、易於理解的日誌檔案用於記錄所有的修改操作。事實上,也可以通過該檔案完成資料的重建。
AOF 方式缺點
-
對於相同數量的資料集而言,AOF檔案通常要大於RDB檔案,持久化檔案會變的越來越大。
-
根據同步策略的不同,AOF在執行效率上往往會慢於RDB。
其他方式
虛擬記憶體方式和diskstore方式這裡不做說明
Redis 資料型別和抽象
redis 鍵
Redis的鍵是二進位制安全的,這意味著您可以使用任何二進位制序列作為鍵 。
redis strings
Redis String型別是可以與Redis金鑰關聯的最簡單的值型別。它是Memcached中唯一的資料型別。
使用SET和GET命令是我們設定和檢索字串值的方式。請注意,即使金鑰與非字串值相關聯,SET也將替換已存在於金鑰中的任何現有值。
SET命令有有趣的選項,這是作為附加引數。例如,如果金鑰已經存在,我可能會要求SET失敗,或者相反,如果金鑰已經存在,它只會成功:詳情
> set mykey newval nx
(nil)
> set mykey newval xx
OK
# EX seconds - 設定指定的過期時間,以秒為單位。
# PX 毫秒 - 設定指定的過期時間,以毫秒為單位。
# NX - 僅設定金鑰(如果金鑰尚不存在)。
# XX - 僅設定金鑰(如果金鑰已存在)。
字串的操作還有一些其他的命令,如下:
> set counter 100
OK
> incr counter
(integer) 101
> incr counter
(integer) 102
> incrby counter 50
(integer) 152
INCR
: 解析字串值作為整數,以一增加它,最後將獲得的值作為新的值。還有其他類似的命令,如INCRBY, DECR和DECRBY。在內部,它始終是相同的命令,以稍微不同的方式運作。 (INCR是原子操作,即使是針對相同金鑰釋出INCR的多個客戶端也不會進入競爭狀態 )
GETSET
: 將鍵設定為新值,並將舊值作為結果返回 。
在單個命令中設定或檢索多個鍵的值的能力對於減少延遲也是有用的。因此,有MSET和MGET命令:
> mset a 10 b 20 c 30
OK
> mget a b c # 使用MGET時,Redis返回值陣列。
1) "10"
2) "20"
3) "30"
EXISTS
:返回1或0以表示資料庫中是否存在給定鍵。
DEL
:刪除鍵和關聯值,無論值是什麼。
> set mykey hello
OK
> exists mykey
(integer) 1
> del mykey
(integer) 1
> exists mykey
(integer) 0
可以看到DEL本身如何返回1或0,具體取決於金鑰是否被刪除(它是否存在)(沒有具有該名稱的金鑰)。
有許多與金鑰空間相關的命令,但上面兩個是與TYPE命令一起必不可少的命令,它返回儲存在指定鍵中的值的型別:
> set mykey x
OK
> type mykey
string
> del mykey
(integer) 1
> type mykey
none
redis strings 其他命令說明
命令 | 說明 |
---|---|
INCR key | 將 key 中儲存的數字值增一。 |
INCRBY key num | 將 key 所儲存的值加上給定的增量值(num)。 |
DECR key | 將 key 中儲存的數字值減一。 |
DECRBY key num | key 所儲存的值減去給定的減量值。 |
APPEND key value | 如果 key 已經存在並且是一個字串, APPEND 命令將指定的 value 追加到該 key 原來值的末尾。 |
redis 到期:live時間有限的keys
預設情況下鍵是沒有生存時間的,永不過期,除非使用del來清除鍵。
設定到期時間
設定到期時間方法入下:
-
strings型別,SET命令是可以直接通過EX,PX來指定過期時間。
-
所有型別都可以使用,EXPIRE、PEXPIRE、EXPIREAT、PEXPIREAT 這四個命令來進行生存時間的設定。
命令 | 說明 |
---|---|
EXPIRE KEY #s | 將KEY的生存時間設定為#秒 |
PEXPIRE KEY #ms | 將KEY的生存時間設定為#毫秒 |
EXPIREAT KEY timestamp | 將KEY的生存時間設定為UNIX時間戳,單位為秒 |
PEXPIREAT KEY timestamp | 將KEY的生存時間設定為UNIX時間戳,單位為毫秒 |
TIME | 一個包含兩個字串的列表: 第一個字串是當前時間(以 UNIX 時間戳格式表示),而第二個字串是當前這一秒鐘已經逝去的微秒數。 |
上面這4個命令只是單位和表現形式上的不同,但實際上EXPIRE、PEXPIRE以及EXPIREAT命令的執行最後都會使用PEXPIREAT來實行。
檢視key的到期時間
Key的到期時間可以使用 TTL
和PTTL
來進行檢視,分別返回秒和毫秒單位級別。
清除key的到期時間
可以使用PERSIST
命令移除一個鍵的過期時間 。
> set key 100
OK
> EXPIRE key 100
(integer) 1
> get key
"100"
> ttl key
(integer) 92
> PERSIST key
(integer) 1
> ttl key
(integer) -1
到期時間返回值說明
返回值 | 說明 |
---|---|
-2 | 過期且已刪除 |
-1 | 沒有過期時間設定,即永不過期 |
>0 | 表示距離過期還有多少秒或者毫秒 |