Redis設計與實現:第十章 - RDB持久化

參考:《Redis設計與實現》

1、RDB文件左右

數據庫狀態:
       服務器中非空數據庫以及它們的鍵值對。

數據庫狀態磁盤化:
       Redis是 內存數據庫,它將自己的數據庫狀態存在內存中,所以如果不想辦法將存儲在內存中的數據庫狀態保存到磁盤,一旦進程退出,服務器中的數據庫狀態也會消失不見。
       爲了解決上述問題,Redis提供了RDB持久化功能,這個功能可以將Redis在內存中的數據庫狀態保存到磁盤,避免數據的意外丟失

RDB持久化:
       可以手動觸發,也可以根據服務器配置選項週期性執行,將某個時間點上的數據庫狀態保存到RDB文件中。

RDB文件:
       是一個經過壓縮的二進制文件,通過改文件可以還原生成RDB文件時的數據庫狀態。RDB文件是保存在磁盤上的,所以即使Redis服務器進程退出,只要RDB文件存在,Redis服務器就可以還原數據庫狀態。

       

2、RDB文件的創建和載入

       有兩個命令可以生成RDB文件,分別是SAVEBGSAVE
       

1、SAVE-RDB文件創建

       SAVE命令會阻塞Redis進程,直到RDB文件創建完畢爲止,在服務器進程阻塞期間,服務器不會處理任何命令請求。

SAVE的代碼處理實現:

	def SAVE():
		//創建RDB文件
		rdbSave()

       

2、BGSAVE-RDB文件創建

       BGSAVE命令會派生出一個子進程,通過子進程創建RDB文件,服務器進程(父進程)繼續處理命令請求。

BGSAVE的代碼處理實現:

	def BGSAVE():
		pid = fork()  //fork子進程
		if pid == 0 :
			rdbSave() //RDB文件保存
			signal_parent() //給父進程發送信號
		else if pid > 0:
			handle_request_and_wait_signal() //處理客戶端請求,並輪訓等待子進程的信號
		else:
			handle_fork_error() //處理錯誤的情況

BGSAVE命令執行期間其他命令的可執行性

  • 如果客戶端發送SAVE命令會被服務器拒絕,原因是:避免父進程和子進程同時執行兩個rdbSave調用,產生競爭關係
  • 如果客戶端發送BGSAVE命令會被服務器拒絕,原因是:兩個BGSAVE命令也可能產生競爭關係
  • 如果客戶端發送BGREWRITEAOF(AOF)命令,會被延遲到BGSAVE命令執行結束之後執行,原因:雖然兩個子進程之間不衝突,但是爲了避免兩個子進程同時執行大量的磁盤寫入操作
  • 如果服務器正在執行BGREWRITEAOF命令,客戶端發送BGSAVE命令會被服務器拒絕。
           

3、RDB文件載入

       RDB文件的載入是在服務器啓動時自動執行的,Redis並沒有專門用於載入RDB文件的命令,只要redis服務器啓動時檢測到RDB文件,就會自動載入。

       因爲AOF文件的更新頻率比RDB文件更高,所以如果服務器開啓AOF持久化功能,會優先通過AOF文件來還原數據庫狀態。所以整個的執行過程如下:
在這裏插入圖片描述

       服務器在載入RDB文件的過程中,會一直處於阻塞狀態,直到載入工作完成爲止。
       

3、RDB文件自動間隔性保存

1、save選項配置

       Redis允許用戶通過設置服務器配置save選項,服務器隔一段時間之後會執行一次BGSAVE命令。

save選項對應的代碼結構:

	{
		struct saveparam *saveparams //保存對應配置的數組
		
		struct saveparam{
			time_t seconds  //秒數
			int changes //修改數
		}
	}

save選項默認值和意義:

	save 900 1
	save 300 10
	save 60 10000
	
	##含義
	#第一行:服務器在900秒之內至少進行了1次修改
	#第二行:服務器在300秒之內至少進行了10次修改
	#第三行:服務器在60秒內至少進行了10000次修改
	#只要滿足其中一個條件就會觸發BGSAVE操作	

       

2、具體實現

       Redis服務器通過dirty計數器(操作了多少個數據庫數字就加上多少的值)和lastsave最後一次保存時間,來實現是否執行BGSAVE命令的判斷:

具體的數據結構如下:

	struct redisServer{
		long long dirty  //dirty計數器	
		time_t lastsave  //上一次進行保存的時間信息
	}

       Redis 的服務器週期性函數serverCron默認每隔100毫秒執行一次,通過檢查save選項的條件是否滿足,來判斷是否進行BGSAVE函數的執行。

4、RDB文件結構

       RDB文件結構如下,鍵值對的value存儲可能採用壓縮,存儲的類型也會導致value的多樣化,可參考原書:
在這裏插入圖片描述
地址:RDB文件結構圖解

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