Redis學習一:Redis兩種持久化機制
申明
本文章首發自本人公眾號:壹枝花算不算浪漫,如若轉載請標明來源!
感興趣的小夥伴可關注個人公眾號:壹枝花算不算浪漫
22.jpg
前言
Redis是基於記憶體來實現的NO SQL資料庫,但是我么你都知道存儲在記憶體中的數據,只要伺服器關機,記憶體中的數據就會消失了。
為了避免記憶體中的數據丟失,Redis提供了對持久化的支援。Redis共有RDB和AOF兩種持久化機制。
可以先看下兩種持久化機制原理:
01_Redis中RDB和AOF.jpg
RDB和AOF兩種持久化機制的介紹
RDB持久化機制,對redis中的數據執行周期性的持久化
AOF機制對每條寫入命令作為日誌,以append-only的模式寫入一個日誌文件中,在redis重啟的時候,可以通過回放AOF日誌中的寫入指令來重新構建整個數據集
如果同時使用RDB和AOF兩種持久化機制,那麼在redis重啟的時候,會使用AOF來重新構建數據,因為AOF中的數據更加完整
RDB持久化機制的優點
-
RDB非常適合做冷備,可以將這種完整的數據文件發送到一些遠程的安全存儲上去,比如雲伺服器。
-
RDB對redis對外提供的讀寫服務,影響非常小,可以讓redis保持高性能,因為redis主進程只需要fork一個子進程,讓子進程執行磁碟IO操作來進行RDB持久化即可
-
相對於AOF持久化機制來說,直接基於RDB數據文件來重啟和恢復redis進程,更加快速
RDB持久化機制的缺點
- 如果想要在redis故障時,儘可能少的丟失數據,那麼RDB沒有AOF好。一般來說RDB數據快照文件,都是每隔5分鐘,或者更長時間生成一次,這個時候就得接受一旦redis進程宕機,那麼會丟失最近5分鐘的數據
- RDB每次在fork子進程來執行RDB快照數據文件生成的時候,如果數據文件特別大,可能會導致對客戶端提供的服務暫停數毫秒,或者甚至數秒
AOF持久化機制的優點
- AOF可以更好的保護數據不丟失,一般AOF會每隔1秒,通過一個後台執行緒執行一次fsync操作,最多丟失1秒鐘的數據
- AOF日誌文件以append-only模式寫入,所以沒有任何磁碟定址的開銷,寫入性能非常高,而且文件不容易破損,即使文件尾部破損,也很容易修復
- AOF日誌文件即使過大的時候,出現後台重寫操作,也不回影響客戶端的讀寫。因為再rewrite log的時候,會對其中的指令進行壓縮,創建一份需要恢複數據的最小日誌出來。再創建新日誌文件的時候,老的日誌文件還是照常寫入。當新的merge後的日誌文件ready的時候,再交換老日誌文件即可
- AOF日誌文件的命令通過非常可讀的方式進行記錄,這個特性非常適合做災難性的誤刪除的緊急恢復。比如不小心使用flushall命令清空了所有數據,只要這個時候後台rewrite還沒有發生,那麼就可以立即拷貝AOF文件,將最後一條flushall命令給刪除,然後再將AOF文件放回去,就可以通過恢復機制,自動恢復所有數據
AOF持久化機制的缺點
- 對於同一份數據來說,AOF日誌文件通常比RDB數據快照文件更大
- AOF開啟後,支援的寫QPS會比RDB支援的寫QPS低,因為AOF一般會配置成每秒fsync一次日誌文件,當然,每秒一次fsync,性能也還是很高的
RDB和AOF到底該如何選擇
- 不要僅僅使用RDB,因為那樣會導致丟失很多數據
- 不要僅僅使用AOF,因為這樣會有問題,第一:通過AOF做冷備,沒有RDB做冷備,來的恢復速度更快。第二:RDB每次簡單粗暴生成數據快照,更加健壯,可以避免AOF這種複雜的備份和恢復機制的bug
- 綜合使用AOF和RDB兩種持久化機制,用AOF來保證數據不丟失,作為數據恢復的第一選擇;用RDB來做不同程度的冷備,在AOF文件都丟失或損壞不可用的時候,還可以使用RDB來進行快速的數據恢復
RDB 配置
// 900s內至少達到一條寫命令
save 900 1
// 300秒內至少達到10條寫命令
save 300 10
// 60秒內至少達到10000條寫命令
save 60 10000
也可以手動調用save或者bgsave命令,同步或非同步執行rdb快照生成
RDB持久化機制的工作流程
- redis根據配置自己嘗試去生成rdb快照文件
- fork一個子進程出來
- 子進程嘗試將數據dump到臨時的rdb快照文件中
- 完成rdb快照文件的生成之後,就替換之前舊的快照文件
dump.rdb 每次生成一個新的快照,都會覆蓋之前老的快照文件
AOF 持久化的配置
AOF持久化默認是關閉的,默認是打開RDB持久化配置的。
配置appendonly yes,可以打開AOF持久化
打開AOF持久化之後,redis每次接收一條寫命令,就會寫入日誌文件中,當然是先寫入os cache,然後每隔一定時間再fsync一下。
而且即使AOF和RDB都開啟了,redis重啟的時候也會優先選擇AOF,因為AOF的數據比較完整
可以配置AOF的fsync策略,有三種策略可以選擇:
- always:每次寫入一條數據,立即將這個數據對應的寫離職fsync到磁碟上去,性能非常差
- everysec:每秒將os cache中的數據fsync到磁碟,這個是最常用的,性能比較高
- no:僅僅redis負責將數據寫入os cache就不需要管了,依賴os根據自己的策略將數據刷入到磁碟中
AOF rewrite
redis中的數據時有限的,很多數據可能會自動過期,可能會被用戶刪除,也有可能被redis用快取清除的演算法清理掉
redis中的數據會不斷淘汰掉舊的數據,只有一部分常用的數據會自動保留在redis記憶體中
所以很可能之前已經被清理掉的數據,對應的寫日誌還停留在AOF中,AOF日誌文件就一個,會不斷的膨脹
所以基於上面的原因,AOF會自動在後台每隔一定時間做rewrite操作,比如日誌里已經存放了針對100w數據的寫日誌,而redis記憶體中此時只有10w數據;rewrite會基於當前記憶體中10w數據構建一套最新的日誌到AOF中,覆蓋之前的老日誌
在redis.conf中,可以配置rewrite的策略:
- auto-aof-rewrite-percentage 100
- auto-aof-rewrite-min-size 64mb
大小超過64mb,且比上次增長了100%才會觸發一次rewrite
具體rewrite步驟:
- redis fork一個子進程
- 子進程基於當前記憶體中的數據,構建日誌,開始往一個新的臨時AOF文件中寫入日誌
- redis主進程,接收到client新的寫操作之後,在記憶體中寫入日誌,同時新的日誌也繼續寫入舊的AOF文件
- 用新的日誌文件替換掉舊的日誌文件
AOF破損文件的修復
如果redis在append數據到AOF文件時,機器宕機了,可能會導致AOF文件破損
用redis-check-aof –fix命令來修復破損的AOF文件
AOF和RDB同時工作
- 如果RDB在執行snapshotting操作,那麼redis不會執行AOF rewrite操作。如果redis在執行AOF rewrite,那麼就不會執行RDB snapshotting操作
- 如果RDB在執行snapshotting,此時用戶執行BGREWRITEAOF命令,那麼等RDB快照生成之後,才會去執行AOF rewrite
- 同時有RDB snapshot文件和AOF日誌文件,那麼redis重啟的時候,會優先使用AOF進行數據恢復,因為其中的日誌更完整