Redis持久化存儲(AOF與RDB兩種模式)

Redis中數據存儲模式有2種:cache-only,persistence;

l cache-only即只做為“緩存”服務,不持久數據,數據在服務終止後將消失,此模式下也將不存在“數據恢復”的手段,是一種安全性低/效率高/容易擴展的方式;

l persistence即為內存中的數據持久備份到磁盤文件,在服務重啟後可以恢復,此模式下數據相對安全。

對於persistence持久化存儲,redis提供了兩種持久化方法:

· Redis DataBase(簡稱RDB)

· Append-only file (簡稱AOF)

除了這兩種方法,Redis在早起的版本還存在虛擬內存的方法,現在已經被廢棄。

一、RDB概述

RDB是在某個時間點將數據寫入一個臨時文件,持久化結束後,用這個臨時文件替換上次持久化的文件,達到數據恢復。


優點:使用單獨子進程來進行持久化,主進程不會進行任何IO操作,保證了redis的高性能


缺點:RDB是間隔一段時間進行持久化,如果持久化之間redis發生故障,會發生數據丟失。所以這種方式更適合數據要求不嚴謹的時候


這裡說的這個執行數據寫入到臨時文件的時間點是可以通過配置來自己確定的,通過配置redis在n秒內如果超過m個key被修改這執行一次RDB操作。這個操作就類似於在這個時間點來保存一次Redis的所有數據,一次快照數據。所有這個持久化方法也通常叫做snapshots。

RDB默認開啟,redis.conf中的具體配置參數如下;

snapshot觸發的時機,是有“間隔時間”和“變更次數”共同決定,同時符合2個條件才會觸發snapshot,否則“變更次數”會被繼續累加到下一個“間隔時間”上。snapshot過程中並不阻塞客戶端請求。snapshot首先將數據寫入臨時文件,當成功結束後,將臨時文件重名為dump.rdb。

使用RDB恢復數據:


自動的持久化數據存儲到dump.rdb後。實際只要重啟redis服務即可完成(啟動redis的server時會從dump.rdb中先同步數據)


客戶端使用命令進行持久化save存儲:

一個是在前臺進行存儲,一個是在後臺進行存儲。我的client就在server這臺服務器上,所以不需要連其他機器,直接./redis-cli bgsave。由於redis是用一個主線程來處理所有 client的請求,這種方式會阻塞所有client請求。所以不推薦使用。另一點需要注意的是,每次快照持久化都是將內存數據完整寫入到磁盤一次,並不是增量的只同步髒數據。如果數據量大的話,而且寫操作比較多,必然會引起大量的磁盤io操作,可能會嚴重影響性能。

二、AOF概述

Append-only file,將“操作 + 數據”以格式化指令的方式追加到操作日誌文件的尾部,在append操作返回後(已經寫入到文件或者即將寫入),才進行實際的數據變更,“日誌文件”保存了歷史所有的操作過程;當server需要數據恢復時,可以直接replay此日誌文件,即可還原所有的操作過程。AOF相對可靠,它和

MySQL中bin.log、apache.log、zookeeper中txn-log簡直異曲同工。AOF文件內容是字符串,非常容易閱讀和解析。


優點:可以保持更高的數據完整性,如果設置追加file的時間是1s,如果redis發生故障,最多會丟失1s的數據;且如果日誌寫入不完整支持redis-check-aof來進行日誌修復;AOF文件沒被rewrite之前(文件過大時會對命令進行合併重寫),可以刪除其中的某些命令(比如誤操作的flushall)。


缺點:AOF文件比RDB文件大,且恢復速度慢。


我們可以簡單的認為AOF就是日誌文件,此文件只會記錄“變更操作”(例如:set/del等),如果server中持續的大量變更操作,將會導致AOF文件非常的龐大,意味著server失效後,數據恢復的過程將會很長;事實上,一條數據經過多次變更,將會產生多條AOF記錄,其實只要保存當前的狀態,歷史的操作記錄是可以拋棄的;因為AOF持久化模式還伴生了“AOF rewrite”。


AOF的特性決定了它相對比較安全,如果你期望數據更少的丟失,那麼可以採用AOF模式。如果AOF文件正在被寫入時突然server失效,有可能導致文件的最後一次記錄是不完整,你可以通過手工或者程序的方式去檢測並修正不完整的記錄,以便通過aof文件恢復能夠正常;同時需要提醒,如果你的redis持久化手段中有aof,那麼在server故障失效後再次啟動前,需要檢測aof文件的完整性。


AOF默認關閉,開啟方法,修改配置文件reds.conf:appendonly yes

AOF是文件操作,對於變更操作比較密集的server,那麼必將造成磁盤IO的負荷加重;此外Linux對文件操作採取了“延遲寫入”手段,即並非每次write操作都會觸發實際磁盤操作,而是進入了buffer中,當buffer數據達到閥值時觸發實際寫入(也有其他時機),這是linux對文件系統的優化,但是這卻有可能帶來隱患,如果buffer沒有刷新到磁盤,此時物理機器失效(比如斷電),那麼有可能導致最後一條或者多條aof記錄的丟失。通過上述配置文件,可以得知redis提供了3中aof記錄同步選項:

· always:每一條aof記錄都立即同步到文件,這是最安全的方式,也以為更多的磁盤操作和阻塞延遲,是IO開支較大。

· everysec:每秒同步一次,性能和安全都比較中庸的方式,也是redis推薦的方式。如果遇到物理服務器故障,有可能導致最近一秒內aof記錄丟失(可能為部分丟失)。

· no:redis並不直接調用文件同步,而是交給操作系統來處理,操作系統可以根據buffer填充情況/通道空閒時間等擇機觸發同步;這是一種普通的文件操作方式。性能較好,在物理服務器故障時,數據丟失量會因OS配置有關。

其實,我們可以選擇的太少,everysec是最佳的選擇。如果你非常在意每個數據都極其可靠,建議你選擇一款“關係性數據庫”吧。


AOF文件會不斷增大,它的大小直接影響“故障恢復”的時間,而且AOF文件中歷史操作是可以丟棄的。AOF rewrite操作就是“壓縮”AOF文件的過程,當然redis並沒有採用“基於原aof文件”來重寫的方式,而是採取了類似snapshot的方式:基於copy-on-write,全量遍歷內存中數據,然後逐個序列到aof文件中。因此AOF rewrite能夠正確反應當前內存數據的狀態,這正是我們所需要的;

*rewrite過程中,對於新的變更操作將仍然被寫入到原AOF文件中,同時這些新的變更操作也會被redis收集起來(buffer,copy-on-write方式下,最極端的可能是所有的key都在此期間被修改,將會耗費2倍內存),當內存數據被全部寫入到新的aof文件之後,收集的新的變更操作也將會一併追加到新的aof文件中,此後將會重命名新的aof文件為appendonly.aof,此後所有的操作都將被寫入新的aof文件。如果在rewrite過程中,出現故障,將不會影響原AOF文件的正常工作,只有當rewrite完成之後才會切換文件,因為rewrite過程是比較可靠的。*


觸發rewrite的時機可以通過配置文件來聲明,同時redis中可以通過bgrewriteaof指令人工干預。

因為rewrite操作/aof記錄同步/snapshot都消耗磁盤IO,redis採取了“schedule”策略:無論是“人工干預”還是系統觸發,snapshot和rewrite需要逐個被執行。

AOF rewrite過程並不阻塞客戶端請求。系統會開啟一個子進程來完成。

三.總結:

AOF和RDB各有優缺點,這是有它們各自的特點所決定:

· 1) AOF更加安全,可以將數據更加及時的同步到文件中,但是AOF需要較多的磁盤IO開支,AOF文件尺寸較大,文件內容恢復數度相對較慢。


*2) snapshot,安全性較差,它是“正常時期”數據備份以及master-slave數據同步的最佳手段,文件尺寸較小,恢復數度較快。


可以通過配置文件來指定它們中的一種,或者同時使用它們(不建議同時使用),或者全部禁用,在架構良好的環境中,master通常使用AOF,slave使用snapshot,主要原因是master需要首先確保數據完整性,它作為數據備份的第一選擇;slave提供只讀服務(目前slave只能提供讀取服務),它的主要目的就是快速響應客戶端read請求;但是如果你的redis運行在網絡穩定性差/物理環境糟糕情況下,建議你master和slave均採取AOF,這個在master和slave角色切換時,可以減少“人工數據備份”/“人工引導數據恢復”的時間成本;如果你的環境一切非常良好,且服務需要接收密集性的write操作,那麼建議master採取snapshot,而slave採用AOF。


分享到:


相關文章: