Redis持久化儲存(AOF與RDB兩種模式)
Redis中資料儲存模式有2種:cache-only,persistence;
- cache-only即只做為“快取”服務,不持久資料,資料在服務終止後將消失,此模式下也將不存在“資料恢復”的手段,是一種安全性低/效率高/容易擴充套件的方式;
- 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中的具體配置引數如下;
#dbfilename:持久化資料儲存在本地的檔案
dbfilename dump.rdb
#dir:持久化資料儲存在本地的路徑,如果是在/redis/redis-3.0.6/src下啟動的redis-cli,則資料會儲存在當前src目錄下
dir ./
##snapshot觸發的時機,save <seconds> <changes>
##如下為900秒後,至少有一個變更操作,才會snapshot
##對於此值的設定,需要謹慎,評估系統的變更操作密集程度
##可以通過“save “””來關閉snapshot功能
#save時間,以下分別表示更改了1個key時間隔900s進行持久化儲存;更改了10個key300s進行儲存;更改10000個key60s進行儲存。
save 900 1
save 300 10
save 60 10000
##當snapshot時出現錯誤無法繼續時,是否阻塞客戶端“變更操作”,“錯誤”可能因為磁碟已滿/磁碟故障/OS級別異常等
stop-writes-on-bgsave-error yes
##是否啟用rdb檔案壓縮,預設為“yes”,壓縮往往意味著“額外的cpu消耗”,同時也意味這較小的檔案尺寸以及較短的網路傳輸時間
rdbcompression yes
snapshot觸發的時機,是有“間隔時間”和“變更次數”共同決定,同時符合2個條件才會觸發snapshot,否則“變更次數”會被繼續累加到下一個“間隔時間”上。snapshot過程中並不阻塞客戶端請求。snapshot首先將資料寫入臨時檔案,當成功結束後,將臨時檔案重名為dump.rdb。
使用RDB恢復資料:
自動的持久化資料儲存到dump.rdb後。實際只要重啟redis服務即可完成(啟動redis的server時會從dump.rdb中先同步資料)
客戶端使用命令進行持久化save儲存:
./redis-cli -h ip -p port save
./redis-cli -h ip -p port bgsave
一個是在前臺進行儲存,一個是在後臺進行儲存。我的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功能的開關,預設為“no”,可以通過“yes”來開啟aof功能
##只有在“yes”下,aof重寫/檔案同步等特性才會生效
appendonly yes
##指定aof檔名稱
appendfilename appendonly.aof
##指定aof操作中檔案同步策略,有三個合法值:always everysec no,預設為everysec
appendfsync everysec
##在aof-rewrite期間,appendfsync是否暫緩檔案同步,"no"表示“不暫緩”,“yes”表示“暫緩”,預設為“no”
no-appendfsync-on-rewrite no
##aof檔案rewrite觸發的最小檔案尺寸(mb,gb),只有大於此aof檔案大於此尺寸是才會觸發rewrite,預設“64mb”,建議“512mb”
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
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指令人工干預。
redis-cli -h ip -p port 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。