Redis的RDB持久化

2022-09-29 00:45:08 字數 3803 閱讀 7199

redis是乙個鍵值對資料庫伺服器,伺服器中通常包含著任意個非空資料庫,而每個非空資料庫中又可以包含任意個鍵值對,為了方便起見,我們將伺服器中的非空資料庫以及它們的鍵值對統稱為資料庫狀態。

舉個例子,下圖展示了乙個包含三個非空資料庫的redis伺服器,這三個資料庫以及資料庫中的鍵值對就是該伺服器的資料庫狀態。

因為redis是記憶體資料庫,它將自己的資料庫狀態儲存在記憶體裡面,所以如果不想辦法將儲存在記憶體中的資料庫狀態儲存到磁碟裡面,那麼一旦伺服器程序退出,伺服器中的資料庫狀態也會消失不見。為了解決這個問題,redis提供了rdb持久化功能,這個功能可以將redis在記憶體中的資料庫狀態儲存到磁碟裡面,避免資料意外丟失。

rdb持久化既可以手動執行,也可以根據伺服器配置選項定期執行,該功能可以將某個時間點上的資料庫狀態儲存到乙個rdb檔案中,如下圖所示。

rdb持久化功能所生成的rdb檔案是乙個經過壓縮的二進位制檔案,通過該檔案可以還原生成rdb檔案時的資料庫狀態,如下圖所示。

因為rdb檔案是儲存在硬碟裡面的,所以即使redis伺服器程序退出,甚至執行redis伺服器的計算機停機,但只要rdb檔案仍然存在,redis伺服器就可以用它來還原資料庫狀態。

有兩個redis命令可以用於生成rdb檔案,乙個是s**e,另乙個是bgs**e。

s**e命令會阻塞redis伺服器程序,直到rdb檔案建立完畢為止,在伺服器程序阻塞期間,伺服器不能處理任何命令請求:

redis> s**e //

等待直到rdb檔案建立完畢

ok

和s**e命令直接阻塞伺服器程序的做法不同,bgs**e命令會派生出乙個子程序,然後由子程序負責建立rdb檔案,伺服器程序(父程序)繼續處理命令請求:

redis> bgs**e //

派生子程序,並由子程序建立rdb檔案

background s**ing started

建立rdb檔案的實際工作由rdb.c/rdbs**e函式完成,s**e命令和bgs**e命令會以不同的方式呼叫這個函式,通過以下偽**可以明顯地看出這兩個命令之間的區別:

def s**e(): 

# 建立rdb檔案

rdbs**e()

def bgs**e():

# 建立子程序

pid =fork()

if pid == 0

: # 子程序負責建立rdb檔案

rdbs**e()

# 完成之後向父程序傳送訊號

signal_parent()

elif pid > 0

: # 父程序繼續處理命令請求,並通過輪詢等待子程序的訊號 handle_request_and_wait_signal()

else

: # 處理出錯情況

handle_fork_error()

和使用s**e命令或者bgs**e命令建立rdb檔案不同,rdb檔案的載入工作是在伺服器啟動時自動執行的,所以redis並沒有專門用於載入rdb檔案的命令,只要redis伺服器在啟動時檢測到rdb檔案存在,它就會自動載入rdb檔案。

以下是redis伺服器啟動時列印的日誌記錄,其中第二條日誌dbloaded from disk:...就是伺服器在成功載入rdb檔案之後列印的:

$ redis-server

[7379] 30 aug 21:07:01.270 # server started, redis version 2.9.11

[7379] 30 aug 21:07:01.289 * db loaded from disk: 0.018 seconds

[7379] 30 aug 21:07:01.289 * the server is now ready to accept con

另外值得一提的是,因為aof檔案的更新頻率通常比rdb檔案的更新頻率高,所以:·如果伺服器開啟了aof持久化功能,那麼伺服器會優先使用aof檔案來還原資料庫狀態。·只有在aof持久化功能處於關閉狀態時,伺服器才會使用rdb檔案來還原資料庫狀態。伺服器判斷該用哪個檔案來還原資料庫狀態的流程如圖所示。

載入rdb檔案的實際工作由rdb.c/rdbload函式完成,這個函式和rdbs**e函式之間的關係可以用下圖表示。

當s**e命令執行時,redis伺服器會被阻塞,所以當s**e命令正在執行時,客戶端傳送的所有命令請求都會被拒絕。只有在伺服器執行完s**e命令、重新開始接受命令請求之後,客戶端傳送的命令才會被處理。

因為bgs**e命令的儲存工作是由子程序執行的,所以在子程序建立rdb檔案的過程中,redis伺服器仍然可以繼續處理客戶端的命令請求,但是,在bgs**e命令執行期間,伺服器處理s**e、bgs**e、bgrewriteaof三個命令的方式會和平時有所不同。

首先,在bgs**e命令執行期間,客戶端傳送的s**e命令會被伺服器拒絕,伺服器禁止s**e命令和bgs**e命令同時執行是為了避免父程序(伺服器程序)和子程序同時執行兩個rdbs**e呼叫,防止產生競爭條件。其次,在bgs**e命令執行期間,客戶端傳送的bgs**e命令會被伺服器拒絕,因為同時執行兩個bgs**e命令也會產生競爭條件。

最後,bgrewriteaof和bgs**e兩個命令不能同時執行:

因為bgrewriteaof和bgs**e兩個命令的實際工作都由子程序執行,所以這兩個命令在操作方面並沒有什麼衝突的地方,不能同時執行它們只是乙個效能方面的考慮——並發出兩個子程序,並且這兩個子程序都同時執行大量的磁碟寫入操作,這怎麼想都不會是乙個好主意。

伺服器在載入rdb檔案期間,會一直處於阻塞狀態,直到載入工作完成為止。

因為bgs**e命令可以在不阻塞伺服器程序的情況下執行,所以redis允許使用者通過設定伺服器配置的s**e選項,讓伺服器每隔一段時間自動執行一次bgs**e命令。使用者可以通過s**e選項設定多個儲存條件,但只要其中任意乙個條件被滿足,伺服器就會執行bgs**e命令。

舉個例子,如果我們向伺服器提供以下配置:

s**e 900 1

s**e 300 10

s**e 60 10000

那麼只要滿足以下三個條件中的任意乙個,bgs**e命令就會被執行:

舉個例子,以下是redis伺服器在60秒之內,對資料庫進行了至少10000次修改之後,伺服器自動執行bgs**e命令時列印出來的日誌:

[5085] 03 sep 17:09:49.463 * 10000 changes in 60 seconds. s**ing...

[5085] 03 sep 17:09:49.463 * background s**ing started by pid 5189

[5189] 03 sep 17:09:49.522 * db s**ed on disk

[5189] 03 sep 17:09:49.522 * rdb: 0 mb of memory used by copy-on-write

[5085] 03 sep 17:09:49.563 * background s**ing terminated with suc

Redis 持久化方式 RDB

redis持久化資料的兩種方式之一,另外一種是aof。redis會定期儲存資料快照至乙個rbd檔案中,並在啟動時自動載入rdb檔案,恢復之前儲存的資料。自動觸發 可以在redis的配置檔案中進行設定,以達到滿足條件自動觸發rdb備份。其他可能 主從複製的時候 因為要複製給從節點最新資訊,所以也會觸發...

redis持久化之RDB

redis是乙個非常好的快取中介軟體,就是將我們的資料放到快取中。我們知道快取的讀取是非常快的。但是誰都避免不了伺服器的意外宕機。一旦宕機,快取中的資料就會丟失。redis除了有主備方式來解決宕機之後的資料丟失之外,還有持久化機制。把資料寫在硬碟上,機器宕機之後啟動時會先去硬碟上讀取資料寫進記憶體。...

Redis 持久化方式 RDB

針對redis的話題估計有些讀者已經開始反感了,昨天還是有一些讀者困惑,這就具體講述下redis持久化方式 rdb的實現方式 手動觸發 自動觸發 rdb 的持久化機制,例如以下場景 儲存 rdb 檔案儲存在 dir 配置指定的目錄下,檔名通過 dbfilename 配置指定。可以通過執行config...