28redis持久化之理論介紹
redis持久化:redis如何將內存數據寫入磁盤中
為什么需要持久化?
內存數據一斷電就會消失,那么所有的請求都會打到數據庫中。因此讓redis中的數據長期持有,不管是重啟、故障、恢復、宕機,還是能從磁盤上讀回曾經保存的數據。
一般redis持久化指的是RDB[Redis Database] 和 AOF[Append Only File]。可以選擇其中一種,也可以兩種都使用,將內存數據寫入磁盤中。
- persistent snapshot【RDB】:快照,將數據打包生成rdb文件。用于整體恢復。
- Append Only File【AOF】:將所有寫命令的操作都記錄下來。恢復時挨個挨個重新運行一次。
29 redis持久化之RDB簡介
RDB(Redis數據庫):RDB持久性以指定的時間間隔執行數據集的時間點快照。
實現類似照片記錄效果的方式,就是把某一時刻的數據和狀態以文件的形式寫到磁盤上,也就是
快照。這樣一來即使故障宕機,快照文件也不會丟失,數據的可靠性也就得到了保證。
這個快照文件就稱為RDB文件(dump.rdb),其中,RDB就是Redis DataBase的縮寫。
如果服務器掛了,redis緩存數據在重啟的時候將會通過硬盤里存儲的rgb文件加載回來。
作用:在指定的時間間隔內將內存中的數據集快照寫入磁盤,也就是行話講的Snapshot內存快照,它恢復時再將硬盤快照文件直接讀回到內存里
一鍋端:Redis的數據都在內存中,保存備份時它執行的是全量快照,也就是說,把內存中的所有數據都記錄到磁盤中,一鍋端
Rdb保存的是dump.rdb文件
redis6版本的redis.conf文件中找到snapshotting ,主要用來設置redis中的rdb。
######## SNAPSHOTTING#######
Save the DB on disk:
save <seconds> <changes>
Will save the DB if both the given number of seconds and the given
number of write operations against the DB occurred.In the example below the behavior will be to save:? //發生以下行為將會保存
after 900 sec (15 min) if at least 1 key changed // 15分鐘內有1次修改
after 300 sec (5 min) if at least 10 keys changed // 5分鐘內有10此修改
after 60 sec if at least 10000 keys changed? // 1分鐘內有1萬次修改Note: you can disable saving completely by commenting out all "save" lines.
It is also possible to remove all the previously configured save
points by adding a save directive with a single empty string argument
like in the following example:save ""
save 900 1
save 300 10
save 60 10000
總結:
Redis6.0.16以下
自動觸發:
在 Redie.conf 配置文件中的 SNAPSHOTTING 下配置 save 參數,來觸發Redis的 RDB持久化條件,
比如“save m n”:表示m秒內數據集存在 n 次修改時,自動觸發 bgsave
save 900 1:每隔 900s(15min),如果有超過1個key 發生了變化,就寫一份新的 RDB 文件
save 300 10:每隔 300s(5min),如果有超過10個key 發生了變化,就寫一份新的 RDB 文件
save 60 10000:每隔 60s(1min),如果有超過 10000個key發生了變化,就寫一份新的RDB文件
redis7
除非另有指定,Redis 默認會在以下情況下保存數據庫(持久化):
-
在 3600 秒(1 小時)后,如果至少執行了 1 次修改
-
在 300 秒(5 分鐘)后,如果至少執行了 100 次修改
-
在 60 秒后,如果至少執行了 10000 次修改
30?redis持久化之RDB配置說明
網站說明:
默認情況下,Redis 會將數據集的快照保存到磁盤上的一個名為 dump.rdb
的二進制文件中。
你可以配置 Redis:當在 N 秒內數據集發生了至少 M 次修改時,就自動保存一次數據集,或者你也可以手動調用 SAVE 或 BGSAVE 命令來執行保存操作。
案例5秒2次修改
vim redis7.conf
linux常用快捷鍵:
復制:Ctrl + Shift + C
粘貼:Ctrl + Shift + V
保存并退出:esc? :wq
保存不退出:esc :w
修改文件:i 在當前光標前插入
vim中查找:
輸入
/關鍵詞
然后回車 → 向下查找輸入
?關鍵詞
然后回車 → 向上查找按
n
→ 查找下一個匹配按
N
→ 查找上一個匹配
我沒有修改路徑,所以進入redis.conf還是按照默認的路徑
cd?/usr/local/src/redis路徑
vim redis.conf
save 5 2
修改dump文件保存路徑
修改dump文件名稱
修改后重啟一下配置文件
redis-server redis.conf的文件路徑
操作時的tips: 剛開始配置并沒有成功,但路徑下出現了log文件。檢查后發現是reids端口被占用導致配置失敗。因此重啟配置文件的時候一定要關閉目前的redis進程。【sudo systemctl stop redis?停止已有的 Redis 實例或其他占用該端口的程序】。
31 redis持久化之RDB自動觸發
save 5 2的含義是在5s秒修改兩次就進行快照。如圖,5s內更改一次并不會更新rdb文件。
如何恢復
將備份文件(dump.rdb)移動到redis安裝目錄并啟動服務即可。備份成功后故意用flushdb清空redis,看看是否可以恢復數據
物理恢復,一定服務和備份分機隔離
把當前目錄下的 dump6379.rdb
文件 重命名 為 dump6379.rdb.bak
mv dump6379.rdb dump6379.rdb.bak
在redis中清掉當前數據
FLUSHDB
此時再檢查 /myredis/dumpfiles目錄
因為當我們使用一個提交命令,類似于終止命令時,redis為了保證事物的一致性,也會自動生成rdb文件。
重啟一下配置文件
redis-server redis.conf的文件路徑
再次連接redis服務器后運行keys* 發現redis數據庫為空
因為重新連接時,redis加載的是新生成的rdb文件。而此文件提交時清空了數據庫,因此加載后數據庫也為空。
結論:執行flushall/flushdb命令也會產生dump.rdb文件,但里面是空的,無意義
快捷鍵? 退出redis:輸入quit ,exit或按ctrl+D
物理恢復
首先強制刪除掉/myredis/dumpfiles中的dump6379.rdb文件
rm -f?dump6379.rdb
SHUTDOWN? // 退出
// 發現/myredis/dumpfiles中又生成了dump6379.rdb文件
?SHUTDOWN :
-
SHUTDOWN
是 Redis 的內置命令,會優雅地關閉 Redis 服務。 -
它會將內存中的數據持久化到
dump.rdb
(如果配置了 RDB),然后關閉服務。
再次清除掉/myredis/dumpfiles中的dump6379.rdb文件
把當前目錄下的 dump6379.rdb.bak
文件 重命名 為 dump6379.rdb
此時再重新啟動配置文件,數據庫恢復。
備注:不可以把備份文件dump.rdb和生產redis服務器放在同一臺機器,必須分開各自存儲
以防生產機物理損壞后備份文件也掛了。
32 redis持久化之RDB手動觸發
為什么要手動觸發?假如我們存儲了很重要的數據,那么手動立刻保存更加保險。
redis提供了兩個命令來生成RDB文件,分別是save和bgsave
工作原理(How it works)
每當 Redis 需要將數據集保存到磁盤時,會執行以下操作:
-
Redis 會進行一次 fork 操作(派生一個新進程)。此時會有一個 子進程 和一個 父進程。
-
子進程并不影響出進程的運行,開始將數據集寫入一個 臨時的 RDB 文件。
-
當子進程完成新 RDB 文件的寫入后,它會 替換舊的 RDB 文件。
這種方式使 Redis 能夠利用操作系統的 寫時復制(copy-on-write)機制 來提高效率。
save【一般不適用】
在主程序中執行會阻塞當前redis服務器,直到持久化工作完成。執行save命令期間,Redis不能處理其他命令【包括緩存服務器對外提供服務的功能,若redis數據量很大,則save的過程會嚴重阻礙其他進程的運行】,線上禁止使用
bgsave
Redis會在后臺異步進行快照操作,不阻塞快照同時還可以響應客戶端請求,該觸發方式會fork一個子進程由子進程復制持久化過程。
Redis會使用bgsave對當前內存中的所有數據做快照,這個操作是子進程在后臺完成的,這就允許主進程同時可以修改數據。
fork是什么?:程序【父進程】運行到 fork()
時,會從當前進程中“克隆”出一個一模一樣的新進程【子進程】,兩者并行運行。
LASTSAVE
可以通過lastsave命令獲取最后一次成功執行快照的時間