Redis基礎(三)Redis持久化:RDB與AOF

大雜草 發表於 2020-10-28

什麼是Redis持久化?

Redis是鍵值對的記憶體資料庫,它將資料儲存在記憶體裡。客戶端傳送命令到伺服器,再由伺服器到記憶體裡查詢資料。

image

一旦Redis伺服器程式退出,儲存在記憶體裡的資料就會丟失。

image

為了解決這個問題,Redis提供了持久化機制,即將資料儲存到磁碟裡,以便Redis伺服器程式初始化或重啟後重新載入資料,避免資料丟失。

image

Redis提供兩種持久化方案,分別是RDB(Redis DataBase)和AOF(Append Only File)。

RDB持久化

RDB採用快照的方式來實現持久化,把資料庫資料儲存到RDB檔案裡,也可以通過RDB檔案還原資料庫資料。

image

開啟RDB持久化的方式

RBD是Redis預設的持久化方案,可以通過三種方式來生成RDB檔案:SAVE、BGSAVE和自動觸發,其中前兩種是主動操作,後一種是被動操作,由Redis伺服器控制。

SAVE

SAVE命令會阻塞Redis伺服器程式,直到RDB檔案建立完成,在伺服器程式阻塞期間,伺服器不能處理任何命令請求。

redis> Save // 等待直到RDB檔案建立完成
OK

image

BGSAVE

和SAVE命令直接阻塞伺服器程式不同,BGSAVE命令會fork一個子程式來負責建立RDB檔案,伺服器程式繼續處理命令請求。

redis> BGSAVE // fork子程式,並由子程式建立RDB檔案
Background saving started

image

自動觸發

Redis允許使用者通過設定伺服器配置的save選項,讓伺服器每隔一段時間自動執行一次BGSAVE命令。使用者可以通過save選項設定多個條件,只要滿足其中任意一個條件,伺服器就會執行BGSAVE命令。

save 900 1 // 伺服器在900秒內,至少1次修改
save 300 10 // 伺服器在300秒內,至少10次修改
save 60 10000 // 伺服器在60秒內,至少10000次修改

AOF持久化

除了RDB外,Redis還提供了AOF。與RDB通過儲存資料庫快照不同,AOF是通過儲存命令來記錄資料庫資料的。預設情況下,Redis是沒有開啟AOF的,可以通過配置redis.conf檔案來開啟AOF持久化,關於AOF的配置如下:

# appendonly引數開啟AOF持久化
appendonly no

# AOF持久化的檔名,預設是appendonly.aof
appendfilename "appendonly.aof"

# AOF檔案的儲存位置和RDB檔案的位置相同,都是通過dir引數設定的
dir ./

# 同步策略
# appendfsync always
appendfsync everysec
# appendfsync no

# aof重寫期間是否同步
no-appendfsync-on-rewrite no

# 重寫觸發配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 載入aof出錯如何處理
aof-load-truncated yes

# 檔案重寫策略
aof-rewrite-incremental-fsync yes

AOF持久化實現

AOF需要記錄Redis的每個命令,步驟分為:命令追加(append)、檔案寫入(write)和檔案同步(sync)。

命令追加

當AOF持久化功能處於開啟狀態時,伺服器在執行完一個寫命令之後,會以協議格式將被執行的寫命令追加到伺服器狀態的 aof_buf 緩衝區的末尾。

檔案寫入和同步

關於何時將 aof_buf 緩衝區的內容寫入AOF檔案中,Redis提供了三種策略:

  • appendfsync always:將aof_buf緩衝區中的所有內容寫入並同步到AOF檔案。
  • appendfsync everysec:將aof_buf緩衝區中的所有內容寫入到AOF檔案,如果上次同步AOF檔案的時間距離現在超過1秒,那麼兩次對AOF檔案進行同步,並且這個同步操作是由一個執行緒專門負責執行的。
  • appendfsync no:將aof_buf緩衝區中的所有內容寫入到AOF檔案,但並不對AOF檔案進行同步,何時同步由作業系統來決定。

關於AOF的同步策略是涉及到作業系統的 write 函式和 fsync 函式的,在《Redis設計與實現》中是這樣說明的:

為了提高檔案寫入效率,在現代作業系統中,當使用者呼叫write函式,將一些資料寫入檔案時,作業系統通常會將資料暫存到一個記憶體緩衝區裡,當緩衝區的空間被填滿或超過了指定時限後,才真正將緩衝區的資料寫入到磁碟裡。


這樣的操作雖然提高了效率,但也為資料寫入帶來了安全問題:如果計算機停機,記憶體緩衝區中的資料會丟失。為此,系統提供了fsyncfdatasync同步函式,可以強制作業系統立刻將緩衝區中的資料寫入到硬碟裡,從而確保寫入資料的安全性。

AOF重寫

AOF會記錄每個Redis命令到AOF檔案,隨著時間越來越長,AOF檔案會變得越來越大。如果不加以控制,會對Redis伺服器,甚至對作業系統造成影響,而且AOF檔案越大,資料恢復也越慢。

為了解決AOF檔案體積膨脹的問題,Redis提供AOF檔案重寫功能來對AOF檔案進行“瘦身”。Redis通過建立一個新的AOF檔案來替換現有的AOF,新舊兩個AOF檔案儲存的資料相同,但新AOF檔案沒有了冗餘命令。

RDB和AOF對比

關於RDB和AOF的優缺點,官網上面也給了比較詳細的說明redis.io/topics/pers…

RDB

優點:

  • RDB快照是一個壓縮過的非常緊湊的檔案,儲存著某個時間點的資料集,適合做資料的備份,災難恢復;
  • 可以最大化Redis的的效能,在儲存RDb檔案,伺服器程式只需要fork一個子程式來完成RDB檔案的建立,父程式不需要做IO操作;
  • 與AOF相比,恢復大資料集的時候會更快;

缺點:

  • RDB的資料安全性是不如AOF的,儲存整個資料集的過程是比繁重的,根據配置可能要幾分鐘才快照一次,如果伺服器當機,那麼就可能丟失幾分鐘的資料;
  • Redis資料集較大時,fork的子程式要完成快照會比較耗CPU、耗時;

AOF

優點:

  • 資料更完整,安全性更高,秒級資料丟失(取決fsync策略,如果是everysec,最多丟失1秒的資料);
  • AOF檔案是一個只進行追加的日誌檔案,且寫入操作是以Redis協議的格式儲存的,內容是可讀的,適合誤刪緊急恢復;

缺點:

  • 對於相同的資料集,AOF檔案的體積要大於RDB檔案,資料恢復也會比較慢;
  • 根據所使用的fsync策略,AOF的速度可能會慢於RDB。 不過在一般情況下,每秒fsync的效能依然非常高;

RDB和AOF如何選擇

通常來說,應該同時使用兩種持久化方案,以保證資料安全。

  • 如果資料不敏感,且可以從其他地方重新生成,可以關閉持久化。
  • 如果資料比較重要,且能夠承受幾分鐘的資料丟失,比如快取等,只需要使用RDB即可。
  • 如果是用做記憶體資料,要使用Redis的持久化,建議是RDB和AOF都開啟。

當RDB與AOF兩種方式都開啟時,Redis會優先使用AOF恢復資料,因為AOF儲存的檔案比RDB檔案更完整。

參考資料