申明
本文章首發自本人公衆號:壹枝花算不算浪漫,如若轉載請標明來源!java
感興趣的小夥伴可關注我的公衆號:壹枝花算不算浪漫redis
前言
Redis是基於內存來實現的NO SQL數據庫,可是我麼你都知道存儲在內存中的數據,只要服務器關機,內存中的數據就會消失了。算法
爲了不內存中的數據丟失,Redis提供了對持久化的支持。Redis共有RDB和AOF兩種持久化機制。數據庫
能夠先看下兩種持久化機制原理: 緩存
RDB和AOF兩種持久化機制的介紹
RDB持久化機制,對redis中的數據執行週期性的持久化安全
AOF機制對每條寫入命令做爲日誌,以append-only的模式寫入一個日誌文件中,在redis重啓的時候,能夠經過回放AOF日誌中的寫入指令來從新構建整個數據集服務器
若是同時使用RDB和AOF兩種持久化機制,那麼在redis重啓的時候,會使用AOF來從新構建數據,由於AOF中的數據更加完整app
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 配置
save 900 1
save 300 10
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進行數據恢復,由於其中的日誌更完整