Redis設計與實現——第二部分 單機數據庫的實現 第10章 rdb持久化

Redis數據庫狀態:服務器中的非空數據庫以及它們的鍵值對統稱爲數據庫狀態。
因爲Redis是內存數據庫,它將自己的數據庫狀態存儲在內存裏面,所以如果不想辦法將存儲在內存總的數據庫狀態保存到磁盤裏面,那麼一旦服務器進程退出,服務器中的數據庫狀態也會消失不見。
Redis rdb持久化功能,可以把某個時間點上redis在內存中的數據庫狀態保存到磁盤裏面一個RDB二進制文件中,避免數據意外丟失,redis服務器可以用它來還原數據庫狀態。

RDB文件的創建與載入
有兩個命令可以用於生成RDB文件,一個是save(阻塞Redis服務器進程),另一個是bgsave(派生出一個子進程,然後由子進程負責創建RDB文件,服務器進程繼續處理命令請求)。

def SAVE() :

創建RDB文件

rdbSave()
def BGSAVE() :

創建子進程

pid = fork()
if pid ==0 :

子進程負責創建RDB文件

rdbSave()

#完成之後向父進程發送信號
signal_parent()

elif pid > 0 :

父進程繼續處理命令請求,並通過輪訓等待子進程的信號

handle_request_and_wait_signal()
else :

處理出錯情況

handle_fork_error()

利用save命令或者bgsave命令創建rdb文件不同,rdb文件的載入工作是在服務器啓動時自動執行的,所以Redis並沒有專門用於載入rdb文件的命令,只要redis服務器在啓動的時候檢測到rdb文件存在,它就會自動載入rdb文件。另外,因爲aof文件的更新頻率通常比rdb文件的更新頻率高,所以1.如果服務器開啓了aof持久化功能,那麼服務器會優先使用aof文件來還原數據庫狀態 2.只有aof處於關閉狀態時,服務器纔會使用rdb文件來還原數據庫狀態。

在這裏插入圖片描述

save命令執行時的服務器狀態
當save命令執行時,redis服務器會被阻塞,所以當save命令正在執行時,客戶端發送的所有命令請求都會被拒絕。
bgsave命令執行時服務器的狀態
客戶端命令可以繼續處理。
save命令禁止執行,兩個命令同時調用rdbSave,防止產生競爭條件。
其次,在bgsave命令執行期間,客戶端發送的bgsave命令會被服務器拒絕,防止產生競爭條件。
再其次,如果客戶端發送bgrewriteaof命令會被延遲到bgsave命令執行完成

如果bgrewriteaof在執行,bgsave命令會被拒絕。
bgrewriteaof和bgsave這兩個命令的實際工作都由子進程執行,所以這個兩個命令在操作方面並沒有什麼衝突的地方,不能同時執行它們只是性能考慮,併發出兩個子進程,並且這兩個子進程都同時執行大量的磁盤寫入操作,這怎麼想都不是一個好主意。

RDB文件載入時服務器一直處於阻塞狀態,知道載入工作完成。

自動間隔性保存
bgsave可以在不阻塞服務器進程的情況下執行,所以redis允許用戶通過設置服務器配置的save選項,讓服務器每隔一段時間執行一次bgsave命令。
用戶可以通過設置save選項設置多個保存條件,但只要其中任意一個條件被滿足,服務器就會執行bgsave命令。

設置保存條件
如果沒有設置save選項,那麼服務器會爲save選項設置默認條件。
save 900 1
save 300 10
save 60 10000
接着服務器程序會根據save選項所設置的保存條件,設置服務器狀態redisServer結構的saveparams屬性:
struct redisServer {
// 記錄了保存條件的數組
struct saveparam *saveparams;
}

struct saveparam {
//秒數
time_t seconds;
//修改數
int changes;
};

在這裏插入圖片描述

dirty計數器和lastsave屬性
除了saveparams數組之外,服務器狀態還維持着一個dirty計數器,以及一個lastsave屬性:
1.dirty計數器記錄距離上一次成功執行save命令或者bgsave命令之後,服務器對數據庫狀態進行了多少次修改
2.lastsave屬性是一個unix時間戳,記錄了服務器上一次執行save命令或bgsave命令的時間。

struct redisServer {
//修改計數器
long long dirty ;
//上一次執行保存的時間 save|bgsave
time_t lastsave;
}

檢查保存條件是否滿足
redis的服務器週期性操作函數serverCron默認每隔100毫秒就會執行一次,該函數用於對正在運行的服務器進行維護,它的其中一項工作就是檢查save選項所設置的保存條件是否滿足,如果滿足就執行bgsave命令。
在這裏插入圖片描述
bgsave執行完後,更新lastsave和dirty計數器。

rdb文件結構
在這裏插入圖片描述
redis,redis字符串
db_version rdb版本 ‘0006’第6版
databases部分包含0個或任意多個數據庫,以及各個數據庫中的鍵值對數據
EOF常量長度爲1字節,這個常量標誌着RDB文件正文內容的結束。
check_sum是一個8字節長的無符號整數,保存着一個校驗和。這個校驗和是程序通過REDIS、db_version、databases、EOF四個部分的內容計算得出的。服務器在載入RDB文件時,會將載入數據所計算出的校驗與check_sum所記錄的校驗和進行對比,以此來檢查rdb文件是否有出錯後者損壞的情況出現。
在這裏插入圖片描述

當程序讀入db_number部分之後,服務器會調用select命令,根據讀入的數據庫號碼進行數據庫切換,使得之後讀入的鍵值對可以載入到正確的數據庫中。

key_value_pairs部分
保存了一個或以上數量的鍵值對
不帶過期時間的鍵值對:
在這裏插入圖片描述

帶過期時間的鍵值對
在這裏插入圖片描述

value編碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章