1. 程式人生 > >Redis入門【九】---------持久化(快照與AOF)

Redis入門【九】---------持久化(快照與AOF)

前言

redis(nosql產品)為了內部資料的安全考慮會把本身的資料以檔案形式儲存到硬碟中一份,在伺服器重啟後會把硬碟中的資料恢復到記憶體中,這個過程叫做持久化(persistence),即把資料(如記憶體中的物件)儲存到可永久儲存的儲存裝置中(如磁碟)。

redis提供兩種不同的持久化方法來將資料儲存到硬碟中,一個叫做快照(snapshotting),有的地方也叫Redis DataBase(簡稱RDB)它可以將存在於某一時刻的所有資料都寫入到硬盤裡面;另一個方法是隻追加檔案(append-only file,AOF),他在執行寫命令的時候,將被執行的寫命令複製到硬碟中。


快照持久化(RDB)

redis可以通過建立快照來獲得儲存在記憶體裡面的資料在某個時間點的副本,在建立快照之後,使用者可以對快照進行備份,可以將快照複製到其他的伺服器從而建立具有相同資料的伺服器的副本,還可以將快照留在原地,以便重啟伺服器的時候使用恢復。

看一下關於快照持久化的配置檔案的選項

# 當在規定的時間內,Redis發生了寫操作的個數滿足條件,會觸發發生bgsave命令。
# save <seconds> <changes>
#在900秒(15分鐘)之後,如果至少有1個key發生變化,則dump記憶體快照。
save 900 1 
#在300秒(5分鐘)之後,如果至少有10個key發生變化,則dump記憶體快照。          
save 300 10 
#在60秒(1分鐘)之後,如果至少有10000個key發生變化,則dump記憶體快照。        
save 60 10000  

#是否啟用rdb檔案壓縮,預設為“yes”,壓縮往往意味著“額外的cpu消耗”,檔案小,網路傳輸快
#(如果希望RDB程序節省一點CPU時間,設定為no,但是可能最後的rdb檔案會很大)   
rdbcompression yes 
#redis持久化監控 是否在快照過程中報錯
stop-writes-on-bgsave-error no
#在redis重啟後,從rdb檔案向記憶體寫資料之前,是否先檢測該rdb檔案是否損壞
rdbcompression yes

#dbfilename:持久化資料儲存在本地的檔案
dbfilename     dump.rdb
#持久化資料儲存在本地的路徑
dir ./


​

建立快照的方法

1.bgsave

客戶端可以向redis傳送一個bgsave命令建立一個快照,基本上除了window平臺,都支援。這種方式Redis會呼叫fork建立一個子程序,然後,子程序負責將快照寫入硬碟,而父程序可以繼續接受客戶端的命令請求。

2.save

客戶端也可以利用save命令來進行,建立快照。但是它於上一個bgsave命令不一樣的是,接受到save的redis伺服器,在建立快照完成之前,是不會再去響應其他的命令,也就是會阻塞到這裡,直到快照建立完畢。它沒有建立子程序,相對來說就節省記憶體,但是不太友好。

3.配置檔案的save選項

也就是上面配置檔案的前三個,比如save 60 10000,那麼從Redis最近的一次快照之後算起,“當60s也就是一分鐘內,如果有10000次的寫入”,redis就會自動執行bgsave命令。看到上面的配置檔案其實是有三個save配置,那麼當這三個配置中save一個條件滿足,就會執行,這個操作。那麼會有人問,你60秒寫入10000的操作,那麼你300秒肯定有10的寫操作,就是有一個包含關係,為什麼還要多設定暱?其實是為了資料安全,資料變化快的話,備份頻率就高一點(資料相對安全,負載高),資料變化慢,備份頻率就低一點(伺服器負載也低一點)。如果你只是配置了save 60 10000,那麼我在60秒內寫入9999個操作,那麼你沒有備份,到時候如果redis伺服器突然宕機,那麼資料的損失量就不好了。當然也可以全部註釋掉save自動快照

4.接受到關機訊號

例如當redis通過shutdown命令接受到關閉伺服器的請求的時候,他會先進行save命令,然後阻塞所有的客戶端,不再執行客戶端傳送的任何指令,並在快照完成後關閉伺服器。

5.複製伺服器(主從複製)

這個知識點,先總結到這裡,關於複製以後再具體瞭解。如果一個redis伺服器向另一個redis伺服器連到一起,向對方傳送sync的命令的時候,在開始複製操作的時候,如果主伺服器沒有進行bgsave操作或者不是剛執行好bgsave,那麼主伺服器,就會進行bgsave命令。

注意

壓縮選項(rdbcompression):上面配置檔案,對於rdb檔案的壓縮,是當字串長度大於等於21個位元組才會進行

校驗選項(rdbchecksum)    :上面配置檔案提到,在重啟redis的時候,會檢測檔案是否損壞,那麼這個check_sum(校驗和)其實是一個儲存在rdb檔案最後的八個位元組裡面:看一下這個rdb檔案的一個結構

redis(rdb檔案標準) db_version(rdb檔案版本號) databases(資料持久化核心) EOF(結束) check_sum(校驗和)

該值是根據前邊四部分值算出來的,在持久化的時候將該值算出來並寫入rdb檔案的末尾;在根據rdb檔案恢復資料的時候,再根據rdb檔案中的前邊四部分值計算出一個校驗和,然後與當前rdb檔案中的check_sum(即後八個位元組)的內容進行比對,如果一樣,說明沒損壞,如果不一樣,說明前四部分有資料損壞(即該檔案損壞)

關於RDB的檔案恢復:自動的持久化資料儲存到dump.rdb後。實際只要重啟redis服務即可完成(啟動redis的server時會從dump.rdb中先同步資料)


AOF持久化

redis可以通過AOF(append-only-file),簡單來說,就是這種持久化是會將被執行寫命令(例如增刪改)追加到AOF檔案末尾,這樣來記錄資料的變化,類似“日誌”,記錄了命令的歷史寫操作。當需要資料恢復的時候,可以直接replay檔案就可以還原之前的寫操作。當然這裡的IO操作來追加檔案寫命令不是寫一條就追加進去一條,寫命令會先新增到緩衝區,然後作業系統會在某個時刻將緩衝區儲存的內容寫入硬碟。

 還是先來看一下配置檔案中AOF相關選項:

#此選項為aof功能的開關,預設為“no”,可以通過“yes”來開啟aof功能  
appendonly yes  
 
#aof檔案的檔名稱
appendfilename appendonly.aof  
#aof檔案路徑(和上面rdb檔案路徑是一個選項,也就是共用)
dir ./

#指定aof操作中檔案同步策略,有三個合法值:always everysec no,預設為everysec 
appendfsync everysec  
#在aof-rewrite期間,appendfsync是否暫緩檔案同步,"no"表示不暫緩,“yes”表示暫緩,
no-appendfsync-on-rewrite no  
 
#aof檔案rewrite觸發的最小檔案尺寸(mb,gb),預設64mb
auto-aof-rewrite-min-size 64mb  
 
#相對於“上一次”rewrite,本次rewrite觸發時aof檔案應該增長的百分比。  
#每一次rewrite之後,redis都會記錄下此時“新aof”檔案的大小(例如A),那麼當aof檔案增長到A*(1 + p)之後  
#觸發下一次rewrite,每一次aof記錄的新增,都會檢測當前aof檔案的尺寸。  
auto-aof-rewrite-percentage 100

關於這些選項注意點:

appendonly : 修改為yes才可以使用AOF持久化

appendfsync : 同步策略/頻率,也就是多久進行一些命令寫入aof檔案,有三個可選值

①always每一個命令,都立即同步到aof檔案中去,很安全,但是速度慢,因為每一個命令都會進行一次磁碟操作,IO開支較大。會受到硬碟的限制,而且頻繁的讀寫,可能會引起硬碟的壽命減少

②everysec每秒將資料寫一次到aof檔案,redis推薦的方式。如果遇到物理伺服器故障,有可能導致最近一秒內aof記錄丟失,可能為部分丟失。而且當硬碟忙於寫入操作的時候,redis還會優雅的放慢自己的速度來適應硬碟的最大寫入速度。

③no 將寫入工作交給作業系統,由作業系統來判斷緩衝區大小,統一寫到aof檔案,速度快,但是同步頻率低,容易丟資料。

 

no-appendfsync-on-rewrite :在RDB持久化資料的時候,此時的aof操作是否停止,若為yes,則停止在停止的這段時間內,執行的命令會寫入記憶體佇列,等RDB持久化完成後,統一將這些命令寫入aof檔案 該引數的配置是考慮到RDB持久化執行的頻率低,但是執行的時間長,而AOF執行的頻率高,執行的時間短,若同時執行兩個子程序(RDB子程序、AOF子程序)效率會低(兩個子程序都是磁碟讀寫)但是若改為yes可能造成的後果是,由於RDB持久化執行時間長,在這段時間內有很多命令寫入了記憶體佇列,最後導致佇列放不下,這樣AOF寫入到AOF檔案中的命令可能就少了很多,在恢復資料的時候,根據aof檔案恢復就會丟很多資料。 一般選擇no就好。

auto-aof-rewrite-min-size  :重寫/壓縮aof檔案,有些同學可能會想到,AOF如此好用,可以在短時間內定期進行持久化,那麼如果寫命令越來越多,aof是不是會越來越大,佔據大量的硬碟資源,這個時候如果重啟讀取aof檔案還原資料集,豈不是要很長時間;而且還有種極端的情況,就是不斷的增加一個key的值,比如將sum不斷做加一操作,那麼寫命令其實很多,這個時候如果將重複的寫命令變成set直接修改成最後的值,不就好了。其實可以通過gbrewriteaof命令來進行AOF的檔案的重寫(Rewrite),這個命令其實也是個bgsave一樣建立一個子程序來進行aof的重寫。但是我們這個地方用這個選項來自動化配置aof檔案重寫,例如設定auto-aof-rewrite-min-size 64mb,那麼當檔案達到這個大小,它就會自己進行重寫。

auto-aof-rewrite-percentage: rewrite觸發時aof檔案應該增長的百分比,可以設定100以上,這樣redis可以在aof檔案變的更大的情況下才去重寫。


對比總結

無論是快照持久化,還是AOF持久化,將資料持久化到硬碟上都是必要的,但是除了持久化之外,使用者還需要將持久化的檔案備份。這樣就可以防止因為系統重啟或者崩潰的情況下,可以進行資料的恢復,使之資料的完整性越來越好。

快照持久化RDB

①災難恢復,RDB是非常不錯的選擇。因為我們可以非常輕鬆的將一個單獨的檔案壓縮後再轉移到其它儲存介質上。

②效能最大化,對於Redis的服務程序而言,在開始持久化時,它唯一需要做的只是fork出子程序,之後再由子程序完成這些持久化的工作,這樣就可以極大的避免服務程序執行IO操作了。但是,如果當資料集較大時,可能會導致整個伺服器停止服務幾百毫秒,甚至是1秒鐘。

③恢復效率高,啟動效率高,RDB 在恢復大資料集時的速度比 AOF 的恢復速度要快。

④執行效率高,RDB在執行效率上往往會高於AOF。總之,每秒同步策略的效率是比較高的,aof同步禁用策略的效率和RDB一樣高效。

⑤檔案體積小,對於相同的資料集來說,RDB 檔案的體積通常要小於AOF 檔案的體積 。

AOF持久化

①同步持久化,耐久(much more durable),AOF 的預設策略為每秒鐘 fsync 一次,在這種配置下,Redis 仍然可以保持良好的效能,並且就算髮生故障停機,也最多隻會丟失一秒鐘的資料( fsync 會在後臺執行緒執行,所以主執行緒可以繼續努力地處理命令請求)。

②AOF 進行重寫,如果日誌過大,Redis可以自動啟用rewrite機制。即Redis以append模式不斷的將修改資料寫入到老的磁碟檔案中,同時Redis還會創 建一個新的檔案用於記錄此期間有哪些修改命令被執行。因此在進行rewrite切換時可以更好的保證資料安全性。

③AOF檔案易懂, AOF包含一個格式清晰、易於理解的日誌檔案用於記錄所有的修改操作。

參考網址

http://doc.redisfans.com/topic/persistence.html