redis 系列16 持久化 RDB
一.概述
Redis是內存數據庫,一旦服務器進程退出,服務器中的數據庫內存數據狀態也會消失。為了解決這個問題,Redis提供了RDB 持久化功能,這個功能可以將redis在內存中的數據庫狀態保存到磁盤中,避免數據意外丟失。
RDB持久化可以手動執行,也可以根據服務器配置選項定期執行,是在指定的時間間隔,對你的數據進行快照存儲。該RDB文件快照是一個經過壓縮的二進制文件。文件名為dump.rdb,該文件保存在redis目錄下,當redis服務器停機後,只要RDB文件存在,下次重啟Redis服務時就會自動還原數據庫數據狀態。
1.1 RDB文件的創建
通過Redis兩個命令來生成RDB文件,一是SAVE,另一個是BGSAVE。SAVE命令是會阻塞Redis服務器進程,直到RDB文件創建完畢為止,在阻塞期間,服務器不能處理任何命令請求。
127.0.0.1:6379> save -- 等待RDB文件創建完畢 OK
與SAVE不同,BGSAVE命令會派生出一個子進程,然後由子進程負責創建RDB文件,服務器進程(父進程)繼續處理命令請求。當BGSAVE命令在執行期間,客戶端再發送BGSAVE命令會被服務器拒絕,因為同時執行兩個GBSAVE命令也會產生競爭條件。最後BGREWRITEAOF和GBSAVE兩個命令也不能同時執行。
127.0.0.1:6379> bgsave --派生子進程,並由子進程創建RDB文件 Background saving started
1.2 RDB文件載入
和創建文件不同,RDB文件的載入是在服務器啟動時自動執行的,並沒有用於載入RDB文件的命令,只要Redis服務器在啟動時檢測到RDB文件的存在,它就會自動載入RDB文件。能過啟動時日誌記錄可以查看。需要註意的是,如果打開了AOF持久化,那麽服務器會優先使用AOF文件來還原數據庫狀態。
1.3 自動間隔性保存
文件的創建除了SAVE和GBSAVE保存RDB 文件,還可以通過配置SAVE選項,讓服務器每隔一段時間自動執行一次BGSAVE命令。可以配置SAVE選項設置多個保存條件,只要任意一個條件被滿足,服務器就會執行BGSAVE命令。
--默認配置的SAVE選項,保存方式有三種條件,滿足任意一種就可以,如下:127.0.0.1:6379> config get save 1) "save" 2) "900 1 300 10 60 10000"
(1) 服務器在900秒之內,對數據庫進行了至少1次修改。
(2) 服務器在300秒之內,對數據庫進行了至少10次修改。
(3) 服務器在60秒之內,對數據庫進行了至少10000次修改。
1.4 檢查保存條件是否滿足
Redis的服務器周期性操作默認每隔100毫秒就會檢查執行一次,用於對正在運行的服務器進行維護,其中一項工作是檢查save 選項所設置的保存條件是否已經滿足,如果滿足就調用BGSAVE命令。
1.5 RDB工作方式
當Redis需要保存dump.rdb文件時,服務器執行以下操作:
(1)Redis調用forks. 同時擁有父進程和子進程。
(2)子進程將數據集寫入到一個臨時 RDB 文件中。
(3)當子進程完成對新 RDB 文件的寫入時,Redis用新 RDB 文件替換原來的 RDB 文件,並刪除舊的 RDB 文件。
1.6 RDB 文件結構
下面簡單了解一下RDB文件結構,這裏不再深入了解。下面腳本顯示了本機dump.rdb文件的位置。該rdb文件結構中各部分 如下圖表格所示:
[root@xuegod64 redis]# pwd /usr/local/redis [root@xuegod64 redis]# ls -l -rwxrwxrwx 1 root root 1687 11月 22 10:03 dump.rdb
文件結構各部份 |
描述 |
redis |
RDB文件最開頭是REDIS部分,保存五個字符,程序在載入文件時,快速檢查所載入的文件是否是RDB文件 |
Db_version |
一個字符串表示的整數,4個字節,記錄了RDB文件的版本號 |
databases |
該部份包含著0個或任意多個數據庫,以及各數據庫中的鍵值對數據 |
Eof |
占1個字節,標誌著RDB文件正文內容的結束,當程序遇到這個值的時候,就知道所有數據庫的所有鍵值對都已經載入完畢了 |
Check_sum |
占8字節的無符號整數,保存一個校驗和,通過前四部分內容進行計算得出。用來檢查RDB文件是否出錯或者損壞 |
下面通過linux的od命令來查看redis服務器產生的RDB 文件,並指定-c參數可以以ASCII編碼方式打印信息。信息中能直接看到的信息是:第一部分是redis, Db_version部分是0008, Eof部分是372 。
1.7 RDB優勢
(1) RDB是一個非常緊湊的文件,它保存了某個時間點得數據集,非常適用於數據集的備份,比如你可以在每個小時報保存一下過去24小時內的數據,同時每天保存過去30天的數據,這樣即使出了問題你也可以根據需求恢復到不同版本的數據集。
(2)RDB是一個緊湊的單一文件,很方便傳送到另一個遠端數據中心,非常適用於災難恢復。
(3)RDB在保存RDB文件時父進程唯一需要做的就是fork出一個子進程,接下來的工作全部由子進程來做,父進程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能。
(4)與AOF相比,在恢復大的數據集的時候,RDB方式會更快一些。
1.8 RDB缺點
(1)如果數據不允許任何丟失,那麽RDB不適合(雖然可以配置不同的save時間點)。
(2)經常fork子進程來保存數據集到硬盤上,當數據集比較大的時候,fork的過程是非常耗時的,可能會導致Redis在一些毫秒級內不能響應客戶端的請求。
二. RDB持久化測試
(1) 首先關閉redis服務。當關閉服務時報錯,首先檢查一下是否是權限的問題,因為在shutdown命令的時候,會進行save操作,而save需要操作dump.rdb文件,如果沒有權限則會報這個錯。
[root@xuegod64 redis]# redis-cli shutdown (error) ERR Errors trying to SHUTDOWN. Check logs -- 需要放開對dump.rdb文件的寫入權限,服務關閉成功 [root@xuegod64 redis]# redis-cli shutdown [root@xuegod64 redis]# redis-cli
(2) 服務啟動,首先set 寫入一條數據,然後關閉服務進程。
[hsr@xuegod64 redis]$ redis-serverredis.conf 127.0.0.1:6379> set name "test" OK 127.0.0.1:6379> get name "test" 127.0.0.1:6379> exit [hsr@xuegod64 redis]$ redis-cli shutdown
(3)重次重啟服務,查看持久化
查看剛才的鍵值對,發現鍵值對已存在,說明數據持久化保存到了磁盤中,原理是在關閉服務時,會先調用save操作,保存到dump.rdb文件中,在重啟服務後,加載dump.rdb文件。
[hsr@xuegod64 redis]$ redis-serverredis.conf [hsr@xuegod64 redis]$ redis-cli 127.0.0.1:6379> get name "test"
總結:作為RDB快照持久化,如果是正常關閉redis服務,再重啟後數據是不會丟失的,但如果系統崩潰或者強殺,用戶將會丟失最近一次生成快照之後更改的所有數據。
redis 系列16 持久化 RDB