redis 持久化方式
對於persistence持久化存儲,Redis提供了兩種持久化方法:
- Redis DataBase(簡稱RDB)
- 執行機制:快照,直接將databases中的key-value的二進制形式存儲在了rdb文件中
- 優點:性能較高(因為是快照,且執行頻率比aof低,而且rdb文件中直接存儲的是key-values的二進制形式,對於恢復數據也快)
- 使用單獨子進程來進行持久化,主進程不會進行任何IO操作,保證了redis的高性能
- 缺點:在save配置條件之間若發生宕機,此間的數據會丟失
- RDB是間隔一段時間進行持久化,如果持久化之間redis發生故障,會發生數據丟失。所以這種方式更適合數據要求不嚴謹的時候
- Append-only file (簡稱AOF)
- 執行機制:將對數據的每一條修改命令追加到aof文件
- 優點:數據不容易丟失
- 可以保持更高的數據完整性,如果設置追加file的時間是1s,如果redis發生故障,最多會丟失1s的數據;且如果日誌寫入不完整支持redis-check-aof來進行日誌修復;AOF文件沒被rewrite之前(文件過大時會對命令進行合並重寫),可以刪除其中的某些命令(比如誤操作的flushall)
- 缺點:性能較低(每一條修改操作都要追加到aof文件,執行頻率較RDB要高,而且aof文件中存儲的是命令,對於恢復數據來講需要逐行執行命令,所以恢復慢)
- AOF文件比RDB文件大,且恢復速度慢。
除了這兩種方法,Redis在早起的版本還存在虛擬內存的方法,現在已經被廢棄。
一、RDB概述
RDB是在某個時間點將數據寫入一個臨時文件,持久化結束後,用這個臨時文件替換上次持久化的文件,達到數據恢復。
這裏說的這個執行數據寫入到臨時文件的時間點是可以通過配置來自己確定的,通過配置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
- ##如下為900秒後,至少有一個變更操作,才會snapshot
- ##對於此值的設置,需要謹慎,評估系統的變更操作密集程度
- ##可以通過“save “””來關閉snapshot功能 (即禁止使用rdb)
#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消耗”,同時也意味這較小的文件尺寸以及較短的網絡傳輸時間 (如果希望RDB進程節省一點CPU時間,設置為no,但是可能最後的rdb文件會很大)
- rdbcompression yes
- #在redis重啟後,從rdb文件向內存寫數據之前,是否先檢測該rdb文件是否損壞(根據rdb文件中的校驗和check_sum)
- rdbchecksum yes
snapshot觸發的時機,是有“間隔時間”和“變更次數”共同決定,同時符合2個條件才會觸發snapshot,否則“變更次數”會被繼續累加到下一個“間隔時間”上。snapshot過程中並不阻塞客戶端請求。snapshot首先將數據寫入臨時文件,當成功結束後,將臨時文件重名為dump.rdb。
- 以上三條save命令只要發生任一條,bgsave命令都會發生,這就有兩個問題,假設60s內有10000個key發生了改變(寫入、刪除、更新),那麽是否會立即進行持久化呢?在這次持久化之後,假設又過了240s,而在此期間沒有任何的key的改變操作,此時是否要發生一次持久化(因為滿足300s發生了10個key的改變,這裏是改變了10000個key)?
- 不會立即進行持久化:redis默認每隔100ms使用serverCron函數檢查一次save配置的條件是否滿足,滿足則進行bgsave,這樣的話,如果在100ms內,我已經滿足了bgsave的條件,那麽我真正執行bgsave的時候也要等到serverCron執行過來的時候
- 不會再發生持久化:redis有兩個參數dirty(記錄上一次bgsave之後的key的修改數,上邊的在240s內例子就是0)和lastsave(上一次成功執行bgsave命令的時間),配置中的每一個save配置的修改數指的就是dirty,而每一個時間段就是以lastsave為起點計算的。
- 註釋掉所有的save命令,RDB將不起作用
- rdbcompression yes:配置成這樣是不是每一個字符串在存儲到rdb文件中時,都要進行一次壓縮操作?
- 不是:設置為yes之後,只有當字符串的長度大於等於21個字節時,才會進行壓縮
- rdbchecksum yes:這個校驗和存儲在哪裏?為什麽通過比對校驗和可以判斷文件是否損壞?
- 校驗和(check_sum)存儲在RDB文件的最後八個字節中(詳細的RDB文件結構,查看《Redis這基於實現》"第10章 RDB持久化"),簡單的RDB文件結構如下:
- RDB文件開頭的前五個字節"REDIS"是判斷一個文件是不是RDB文件的標準(類似於class文件中的"魔數")
- 接下來的4個字節:RDB文件版本號(db_version)
- databases(註意是復數):這裏存放各個庫redisDb中存儲的key-value信息(是整個數據持久化和恢復的核心)
- EOF(1個字節):RDB文件正文的結束
- check_sum(8個字節):檢驗和,該值是根據前邊四部分值算出來的,在持久化的時候將該值算出來並寫入rdb文件的末尾;在根據rdb文件恢復數據的時候,再根據rdb文件中的前邊四部分值計算出一個校驗和,然後與當前rdb文件中的check_sum(即後八個字節)的內容進行比對,如果一樣,說明沒損壞,如果不一樣,說明前四部分有數據損壞(即該文件損壞)
- 校驗和(check_sum)存儲在RDB文件的最後八個字節中(詳細的RDB文件結構,查看《Redis這基於實現》"第10章 RDB持久化"),簡單的RDB文件結構如下:
- 在Redis服務器啟動時,redis會自動檢測是否有rdb文件(前提是沒有aof的時候),如果有,則根據rdb文件恢復數據,此時在恢復數據完成之前,會阻塞客戶端對redis的讀寫操作
使用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文件內容是字符串,非常容易閱讀和解析。
我們可以簡單的認為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
- ##
- 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數據同步的最佳手段,文件尺寸較小,恢復數度較快
- 如果既配置了RDB,又配置了AOF,則在進行數據持久化的時候,都會進行,但是在根據文件恢復數據的時候,以AOF文件為準,RDB文件作廢
- 需要註意:數據的恢復是阻塞操作(此間所到來的任何客戶端讀寫請求都失效)
- bgsave和bgrewriteaof(後臺aof重寫)這兩個命令不可以同時發生
- 如果bgsave在執行,此間到來的bgrewriteaof在bgsave執行之後,再執行
- 如果bgrewriteaof在執行,此間到來的bgsave丟棄
- RDB和AOF可以同時配置,但是最後還原數據庫的時候是以aof文件來還原的
--------------------- 本文來自 xiaozhu0301 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/xiaozhu0301/article/details/79021436?utm_source=copy
redis 持久化方式