1. 程式人生 > >使用快照和AOF將Redis資料持久化到硬碟中

使用快照和AOF將Redis資料持久化到硬碟中

前言

我們知道Redis是一款記憶體伺服器,就算我們對自己的伺服器足夠的信任,不會出現任何軟體或者硬體的故障,但也會有可能出現突然斷電等情況,造成Redis伺服器中的資料失效。因此,我們需要向傳統的關係型資料庫一樣對資料進行備份,將Redis在記憶體中的資料持久化到硬碟等非易失性介質中,來保證資料的可靠性。

將Redis記憶體伺服器中的資料持久化到硬碟等介質中的一個好處就是,使得我們的伺服器在重啟之後還可以重用以前的資料,或者是為了防止系統出現故障而將資料備份到一個遠端的位置。

還有一些場景,例如:

對於一些需要進行大量計算而得到的資料,放置在Redis伺服器,我們就有必要對其進行資料的持久化,如果需要對資料進行恢復的時候,我們就不需進行重新的計算,只需要簡單的將這臺機器上的資料複製到另一臺需要恢復的Redis伺服器就可以了。

Redis給我們提供了兩種不同方式的持久化方法:快照(Snapshotting)只追加檔案(append-only-file)

(1)名詞簡介

快照(RDB):就是我們俗稱的備份,他可以在定期內對資料進行備份,將Redis伺服器中的資料持久化到硬碟中;

只追加檔案(AOF):他會在執行寫命令的時候,將執行的寫命令複製到硬盤裡面,後期恢復的時候,只需要重新執行一下這個寫命令就可以了。類似於我們的MySQL資料庫在進行主從複製的時候,使用的是binlog二進位制檔案,同樣的是執行一遍寫命令;

(2)快照持久化通用的配置:

save 60 1000  #60秒時間內有1000次寫入操作的時候執行快照的建立
stop-writes-on-bgsave-error no #建立快照失敗的時候是否仍然繼續執行寫命令 rdbcompression yes #是否對快照檔案進行壓縮 dbfilename dump.rdb #如何命名硬碟上的快照檔案 dir ./ #快照所儲存的位置

(3)AOP持久化配置:

appendonly no  #是否使用AOF持久化
appendfsync everysec  #多久執行一次將寫入內容同步到硬碟上
no-appendfsync-on-rewrite no #對AOF進行壓縮的時候能否執行同步操作
auto-aof-rewrite-percentage 100
#多久執行一次AOF壓縮 auto-aof-rewrite-min-size 64mb #多久執行一次AOF壓縮 dir ./ #AOF所儲存的位置

需要注意的是:這兩種持久化的方式既可以單獨的使用,也可以同時使用,具體選擇哪種方式需要根據具體的情況進行選擇。

快照持久化

快照就是我們所說的備份。使用者可以將Redis記憶體中的資料在某一個時間點進行備份,在建立快照之後,使用者可以對快照進行備份。通常情況下,為了防止單臺伺服器出現故障造成所有資料的丟失,我們還可以將快照複製到其他伺服器,建立具有相同資料的資料副本,這樣的話,資料恢復的時候或者伺服器重啟的時候就可以使用這些快照資訊進行資料的恢復,也可以防止單臺伺服器出現故障的時候造成資料的丟失。

但是,沒我們還需要注意的是,建立快照的方式,並不能完全保證我們的資料不丟失,這個大家可以很好的理解,因為快照的建立時定時的,並不是每一次更新操作都會建立一個快照的。系統發生崩潰的時候,使用者將丟失最近一次生成快照之後更改的所有資料。因此,快照持久化的方式只適合於資料不經常修改或者丟失部分資料影響不大的場景。

一、建立快照的方式:

(1)客戶端通過向Redis傳送BGSAVE 命令來建立快照。

使用BGSAVE的時候,Redis會呼叫fork來建立一個子程序,然後子程序負責將快照寫到硬碟中,而父程序則繼續處理命令請求。

使用場景:

如果使用者使用了save設定,例如:save 60 1000 ,那麼從Redis最近一次建立快照之後開始計算,當“60秒之內有1000次寫入操作”這個條件滿足的時候,Redis就會自動觸發BGSAVE命令。

如果使用者使用了多個save設定,那麼當任意一個save配置滿足條件的時候,Redis都會觸發一次BGSAVE命令。

(2)客戶端通過向Redis傳送SAVE 命令來建立快照。

接收到SAVE命令的Redis伺服器在快照建立完畢之前將不再響應任何其他命令的請求。SAVE命令並不常用,我們通常只在沒有足夠的記憶體去執行BGSAVE命令的時候才會使用SAVE命令,或者即使等待持久化操作執行完畢也無所謂的情況下,才會使用這個命令;

使用場景:

當Redis通過SHUTDOWN命令接收到關閉伺服器的請求時,或者接收到標準的TERM訊號時,會執行一次SAVE命令,阻塞所有的客戶端,不再執行客戶端傳送的任何命令,並且在執行完SAVE命令之後關閉伺服器。

二、使用快照持久化注意事項:

我們在使用快照的方式來儲存資料的時候,如果Redis伺服器中的資料量比較小的話,例如只有幾個GB的時候。Redis會建立子程序並將資料儲存到硬盤裡邊,生成快照所需的時間比讀取資料所需要的時間還要短。

但是,隨著資料的增大,Redis佔用的記憶體越來越大的時候,BGSAVE在建立子程序的時候消耗的時間也會越來越多,如果Redis伺服器所剩下的記憶體不多的時候,這行BGSAVE命令會使得系統長時間地停頓,還有可能導致伺服器無法使用。

各虛擬機器類別,建立子執行緒所耗時間:

這裡寫圖片描述

因此,為了防止Redis因為建立子程序的時候出現停頓,我們可以考慮關閉自動儲存,轉而通過手動的方式傳送BGSAVE或者SAVE來進行持久化,

手動的方式傳送BGSAVE也會出現停頓的現象,但是我們可以控制傳送該命令的時間來控制出現停頓的時候不影響具體的業務請求。

另外,值得注意的是,在使用SAVE命令的時候,雖然會一直阻塞Redis直到快照生成完畢,但是其不需要建立子程序,所以不會向BGSAVE一樣,因為建立子程序而導致Redis停頓。也正因為如此,SAVE建立快照的速度要比BGSAVE建立快照的速度更快一些。

建立快照的時候,我們可以在業務請求,比較少的時候,比如凌晨三、四點,通過手寫指令碼的方式,定時執行。

AOF持久化

AOF持久化會將被執行的寫命令寫到AOF檔案的末尾,以此來記錄資料發生的變化。這樣,我們在恢復資料的時候,只需要從頭到尾的執行一下AOF檔案即可恢復資料。

一、開啟AOF持久化選項

我們可以通過使用如下命令開啟AOF:

appendonly yes

我們,通過如下命令來配置AOF檔案的同步頻率:

appendfsync everysec/always/no

二、appendfsync同步頻率的區別

appendfsync同步頻率的區別如下圖:

這裡寫圖片描述

(1)always的方式固然可以對沒一條資料進行很好的儲存,但是這種同步策略需要對硬碟進行大量的寫操作,所以Redis處理命令的速度會受到硬碟效能的限制。

普通的硬碟每秒鐘只能處理大約200個寫命令,使用固態硬碟SSD每秒可以處理幾萬個寫命令,但是每次只寫一個命令,這種只能怪不斷地寫入很少量的資料的做法有可能引發嚴重的寫入放大問題,這種情況下降嚴重影響固態硬碟的使用壽命。

(2)everysec的方式,Redis以每秒一次的頻率大隊AOF檔案進行同步。這樣的話既可以兼顧資料安全也可以兼顧寫入效能。

Redis以每秒同步一次AOF檔案的效能和不使用任何持久化特性時的效能相差無幾,使用每秒更新一次 的方式,可以保證,即使出現故障,丟失的資料也在一秒之內產生的資料。

(3)no的方式,Redis將不對AOF檔案執行任何顯示的同步操作,而是由作業系統來決定應該何時對AOF檔案進行同步。

這個命令一般不會對Redis的效能造成多大的影響,但是當系統出現故障的時候使用這種選項的Redis伺服器丟失不定數量的資料。

另外,當用戶的硬碟處理寫入操作的速度不夠快的話,那麼緩衝區被等待寫入硬碟的資料填滿時,Redis的寫入操作將被阻塞,並導致Redis處理命令請求的速度變慢,因為這個原因,一般不推薦使用這個選項。

三、重寫/壓縮AOF檔案

隨著資料量的增大,AOF的檔案可能會很大,這樣在每次進行資料恢復的時候就會進行很長的時間,為了解決日益增大的AOF檔案,使用者可以向Redis傳送BGREWRITEAOF 命令,這個命令會通過移除AOF檔案中的冗餘命令來重寫AOF檔案,是AOF檔案的體檢變得儘可能的小。

BGREWRITEAOF的工作原理和BGSAVE的原理很像:Redis會建立一個子程序,然後由子程序負責對AOF檔案的重寫操作。

因為AOF檔案重寫的時候匯建立子程序,所以快照持久化因為建立子程序而導致的效能和記憶體佔用問題同樣會出現在AOF檔案重寫的 時候。

四、觸發重寫/壓縮AOF檔案條件設定

AOF通過設定auto-aof-rewrite-percentageauto-aof-rewrite-min-size 選項來自動執行BGREWRITEAOF。

其具體含義,通過例項可以看出,如下配置:

auto-aof-rewrite-percentage 100 
auto-aof-rewrite-min-size 64mb

表示當前AOF的檔案體積大於64MB,並且AOF檔案的體積比上一次重寫之後的體積變大了至少一倍(100%)的時候,Redis將執行重寫BGREWRITEAOF命令。

如果AOF重寫執行的過於頻繁的話,可以將auto-aof-rewrite-percentage 選項的值設定為100以上,這種最偶發就可以讓Redis在AOF檔案的體積變得更大之後才執行重寫操作,不過,這也使得在進行資料恢復的時候執行的時間變得更加長一些。

驗證快照檔案和AOF檔案

無論使用哪種方式進行持久化,我們在進行恢復資料的時候,Redis提供了兩個命令列程式:

redis-check-aof
redis-check-dump

他們可以再系統發生故障的時候,檢查快照和AOF檔案的狀態,並對有需要的情況對檔案進行修復。

如果使用者在執行redis-check-aof命令的時候,指定了--fix 引數,那麼程式將對AOF檔案進行修復。

程式修復AOF檔案的方法很簡單:他會掃描給定的AOF檔案,尋找不正確或者不完整的命令,當發現第一個出現錯誤命令的時候,程式會刪除出錯命令以及出錯命令之後的所有命令,只保留那些位於出錯命令之前的正確命令。大部分情況,被刪除的都是AOF檔案末尾的不完整的寫命令。

總結

上述,一起學習了兩種支援持久化的方式,一方面我們需要通過快照或者AOF的方式對資料進行持久化,另一方面,我們還需要將持久化所得到的檔案進行備份,備份到不同的伺服器上,這樣才可以儘可能的減少資料丟失的損失。

參考文章:

1、Redis in Action - [美] Josiah L.Carlsono