1. 為什麼需要持久化?
Redis的讀寫和響應速度為什麼如此之快?不同於傳統的關係型資料庫,Redis的資料庫是全部載入在實時記憶體中的,讀寫操作能夠直接在記憶體中進行,省去了大量IO操作,因此效能非常優越。但一切依託於記憶體的服務都有個最大的軟肋,那便是在裝置出現故障(如斷點)時,記憶體中所有的實時資料都將會丟失。為了解決這個問題,Redis中提供了兩種持久化方案:RDB和AOF,其機制實際上都是設法將記憶體中的資料以檔案的形式備份到磁碟上,從而解決斷電等機器故障導致資料丟失的問題。
2. RDB (Redis DataBase)
實現機制:Redis會單獨建立(fork)一個子程式來進行持久化,會先將資料寫入到一個臨時檔案中,待持久化過程結束後,再用這個臨時檔案替換上次持久化好的檔案(dump.rdb)。整個過程中,主程式不會進行任何IO操作的,這樣就能夠保證Redis主程式持續的高效能。在恢復資料時,重啟後會Redis會自動載入工作目錄下的dump.rdb檔案恢復資料到記憶體
相關引數:
## 設定觸發RDB dump的條件,在<seconds>時間至少發生了<changes>次資料的操作,則<seconds>時間到了就將資料寫到磁碟中,為dump.rdb Redis預設設定了三個條件,滿足之一即可觸發。移除所有條件或者設定 save 後加空字串為禁用RDB功能
save <seconds> <changes>
save 900 1 ## for 低頻寫入
save 300 10 ## for 中頻寫入
save 60 10000 ## for 高頻寫入
## 設定當RDB程式出現故障時,Redis是否停止寫操作,預設為yes
stop-writes-on-bgsave-error yes
## 設定RDB時是否使用LZF壓縮演算法對dump.rdb檔案進行壓縮,預設yes
rdbcompression yes
## 設定是否對dump.rdb檔案進行校驗,預設CRC64校驗演算法,會消耗RDB程式的CPU資源的10%,預設開
rdbchecksum yes
## 設定輸出檔名, 預設dump.rdb
dbfilename dump.rdb
## 設定dump.rdb檔案輸出路徑,預設為當前啟動工作目錄
dir ./
優勢:
- 無論是持久化過程還是資料恢復過程,RDB的速度都非常快
- 使用者能夠手動設定引數以控制持久化的頻率,應用場景更加靈活
- 適合大規模且對資料的完整性和一致性要求不高的資料恢復,
劣勢:
- RDB的持久化需要fork一條子執行緒,且子執行緒將會copy主執行緒所有資料,相當於裝置的記憶體使用臨時翻了一倍,在資料量特別大的情況下使用RDB可能有記憶體溢位風險
- 最後一次持久化的資料可能丟失,因此對資料完整性比較敏感的業務不建議使用RDB進行持久化
PLUS:為什麼最後一次持久化的資料可能丟失?
RDB通過設定save <seconds> <changes>條件來觸發dump,其機制為滿足任一save條件後再該條件的<seconds>後進行刷寫,但實際上可能最後一次dump時雖然達到修改次數<changes>要求,但在時間還未到達時redis程式中止,則這一階段的資料就丟失了。比如save 300 10這一條件,Redis在300s內的修改操作次數超過了10次,因此觸發持久化條件,系統將會在300s到期後進行刷寫,但是可能在到期前幾秒,裝置異常關機,那麼這300s內產生的資料修改資訊將會全部丟失
3. AOF(Append Only File)
實現機制:與RDB直接寫原資料不同,AOF記錄的是Redis自啟動期間所有的寫操作,類似於日誌,且寫入的方式只允許在末尾追加,不允許修改之前寫入的內容,預設儲存為appendonly.aof檔案。恢復資料時,Redis將AOF載入到記憶體並執行其中的每一條資料進行資料的恢復。
相關引數:
## 啟動開關 -- 預設關閉
appendonly no
## 檔名
appendfilename "appendonly.aof"
## 刷寫頻率
appendfsync always ## 同步持久化,每當有資料變更就立即記錄到磁碟,效能較差但資料完整性好
appendfsync everysec ## 出廠預設配置,非同步操作,每秒記錄,如果一秒內當機,則會有資料丟失
append no ## 不設定刷寫頻率,當Redis自己觸發刷寫條件時才進行刷寫
優勢:
- 預設的刷寫頻率為每秒一次,因此能夠最大程度地保證資料的完整性
- AOF只是記錄執行時的寫操作,並不會複製所有主執行緒資料,因此發生記憶體溢位的風險較小
劣勢:
- 只支援追加形式寫入,因此形成的appendonly.aof檔案會越來越大,會影響Redia恢復資料的效能
- 恢復資料時需要Redis執行appendonly.aof記錄的每條指令,恢復速度較慢
- 實際上操作指令有很大的整合空間,比如10000條自增1語句可以歸併為一條自增10000語句,AOF在這方面仍然有較大可優化空間
Rewrite機制:為解決appendonly.aof檔案會越來越大的隱患,AOF設定了Rewrite機制,預設當appendonly.aof檔案大小達到了上次Rewrite後appendonly.aof檔案的大小時並且檔案的大小超過64M,AOF將會啟動Rewrite,fork出一條新程式建立一個臨時檔案,然後遍歷整個資料庫,將每個key、value對以Redis命令的格式輸出到臨時檔案。這一過程會將多個鍵值對集合起來用一條命令表達以減小最終檔案的大小。在rewrite期間的寫操作會儲存在記憶體的rewrite buffer中,rewrite成功後這些操作也會append到臨時檔案中,rewrite完成後該臨時檔案便會代替appendonly.aof檔案
## 觸發Rewrite條件 -- and --
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
## 發生重寫時是否支援appendfsync刷寫? 預設為no,保證資料安全
no-appendfsync-on-rewrite no
4. 小結
使用場景:
- RDB適合資料流大、資料恢復快但對資料完整性依賴不高的業務,比如使用者行為分析等
- AOF則適合對資料完整性有很高限制的業務,比如銀行金融類業務
共存性:
官方雖然預設關閉AOF功能,但實質上RDB和AOF是可以共存的,當Redis同時開啟了AOF和RDB持久化,Redis重啟時會優先讀取AOF檔案進行資料恢復,因為AOF比RDB更能保證資料完整性。此外,由於Redis資料的恢復需要讀取AOF檔案或者RDB檔案,因此,為了防止這兩個檔案出現損毀或者被惡意修改,Redis提供了兩個修復指令碼專門修復這兩個檔案
## 修復AOF檔案
redis-check-aof --fix appendonly.aof
## 修復RDB檔案
redis-check-dump --fix dump.rdb
安全性擴充:
實際生產時,無論是AOF還是RDB,都需要將生成的appendonly.aof和dump.rdb檔案進行異地備份,這樣才能避免單機徹底損壞造成的資料不可恢復問題