什么是redis持久化?
Redis持久化是將內存的數據持久化到磁盤上,防止Redis宕機或者斷點的時候內存中的數據丟失,把內存中的數據寫入到磁盤的過程叫持久化。
Redis持久化的方式?
- RDB(Redis DataBase):在指定時間間隔內將內存中的數據以快照的方式寫入到磁盤上,Redis默認的持久化方式。
- AOF(Append Of File):以日志的形勢記錄每個寫命令、刪除命令。
- 混合持久化:混合持久化并不是一種全新的持久化方式,它只是同時使用了RDB和AOF兩種模式,是Redis 4.0版本開啟的功能,通過aof-use-rdb-preamble配置參數開啟,yes表示開啟,no表示禁用,默認禁用。
RDB持久化詳解:
RDB持久化流程:
- 客戶端觸發或者自動執行bagesave命令。
- 主進程判斷是否存在正在執行的子進程,存在返回。
- 不存在的話fork一個子進程進行持久化數據,fork過程中是阻塞的,fork操作完成后,主進程即可執行其他操作。
- 子進程先將數據寫入臨時rdb文件中,數據寫入完成后替換舊的rdb文件,同時通知主進程RDB持久化完成。
RDB持久化的優缺點:
優點:
- 文件緊湊,全量備份,適合數據備份和災難恢復。
- 生成RDB文件時,redis主進程會fork()一個子進程來保存工作,主進程不需要進行任何IO操作。
- RDB在恢復大數據集時速度比AOF的恢復速度要快。
缺點:
- 因為RDB需要保存整個數據集,所以不是一個輕松的操作,因此一般不會設置太短時間,因此一段發生故障停機,會丟失幾分鐘的數據。
- 如果數據集過大的情況下,所fork子進程在協助完成持久化時,所可能導致服務器停止幾百毫秒,所甚至幾秒鐘。
AOF持久化流程:
AOF文件只記錄寫命令,不記錄讀命令,當服務端接收到寫命令后,redis會將命令寫入到aof緩沖區中,只所以寫入緩沖區而不直接寫入到文件中,是因為每次直接將命令寫入文件中,那redis的性能將完全取決于硬盤的讀寫能力,影響redis性能。
AOF工作流程圖:
AOF三種同步策略:
- always(總是):每次執行了寫入或刪除的命令寫入緩沖區后,就調用系統fsync將redis執行的命令寫入aof文件中,fsync操作完成后主線程返回。
- no:命令寫入緩沖區后,調用操作系統的write操作,Redis不主動將命令同步到aof文件中,同步動作由操作系統來負責,一般是30秒一次。
- everysec:命令寫入緩沖區后,調用操作系統的write操作,write操作完成之后,有專門的線程每秒執行fsync操作。
AOF持久化的優缺點:
優點:
- AOF持久化幾乎不丟失數據,最多丟失一秒的數據。
- AOF機制采用的是append模式,因此即使在寫入過程發生宕機,也不會破壞日志文件中已經存在的內容,如果本次操作只寫入了一半就出現了系統宕機,redis下一次重啟的時候,可以通過redis-check-aof來解決數據一致性問題。
- 如果日志文件過大,redis可以自動啟用rewriter機制,redis以append模式不斷的將修改數據寫入到磁盤中,同時會創建一個新的文件記錄此期間有哪些命令被修改,在rewriter期間可以更好的保證數據安全性。
- AOF包含一個格式清晰易于理解的日志文件,也可以通過該文件完成數據重建。
缺點:
- 對于相同的數據集來說,AOF的文件體積一般大于RDB文件的體積。
- 對redis性能有一定的損耗。
- 相對RDB持久化的方式的數據恢復速度,AOF持久化的方式數據恢復速度會更慢一些。
AOF rewrite重寫機制是什么意思?
AOF 重寫是為了縮小aof文件,AOF持久化模式是不斷的記錄Redis寫入、刪除命令到文件中,隨著命令的越來越多,文件會越來越大,aof重寫會把過程操作過程去掉,把多個命令合并成一個命令,這樣就縮小了AOF文件。
AOF rewrite作用:
- 使aof文件變的更小,占用更少的磁盤空間。
- aof文件編的更小后,在數據恢復的時候會更快。
AOF rewrite流程圖:
AOF 重寫規則?
- 進程內已經過期的數據不再寫入文件。
- 只保存最終的寫入命令,如set a 1,set a 2,set a 3,此時只保留set a 3。
- 多條寫命令合并為一條命令,如lpush list 1,lpush list 2,lpush list 3,合并為lpush list 1,2,3,同時為了防止單條命令過大,對于list set zset hash 等以64個元素為界限拆分為多條命令。
什么是混合持久化?
混合持久化是redis4.0版本添加的新功能,通過aof-use-rdb-preamble配置參數開啟,yes表示開啟,no表示禁用,默認禁用,混合持久化體現在aofrewrite時,先寫一份全量RDB數據到aof文件中,后續AOF重寫緩沖區里的數據繼續追加到該文件中,因為開啟了混合持久化后,appendonly.aof文件開頭是RDB格式,后續是AOF格式。
使用混合持久化后,Redis在重啟數據恢復時候,會先加載RDB的內容,然后再執行AOF日志就可以完全替代之前的AOF全量文件執行,重啟數據恢復的速度得到大大提升。
Redis進行持久化的時候會阻塞主線程嗎?
fork子進程過程是阻塞的,fork過程就是創建一個主進程的副本,創建的子進程除了進程id,其余任何內容和主進程完全一致,這就是fork,fork的子進程獨立于主進程存在,雖然兩個進程內存空間內容完全一致,但是對于內存的寫入、修改以及文件的映射都是獨立的,兩個進程互不影響,開啟aof持久化,使用everysec同步策略時,會發生aof追加阻塞,出現aof阻塞的原因是磁盤負載過高,redis主進程會監控同步線程每次她同步aof緩沖區到aof文件的消耗時間,如果距離上次同步成功時間在2S內,那么主線程就會返回,如果超過2S,redis主進程會阻塞,直到同步完成,不管是RDB還是AOF持久化,都會使用fork創建一個子進程來處理,fork出來的子進程不會阻塞主進程,但是fork的過程還是會阻塞主進程,一般來說主進程內存越大,需要復制的空間內存葉也比較大,fork所需的時間也會長,redis阻塞的時間越長。
本文偏概念、偏面試八股,但學習理解了不管是對工作還是對面試都是有一定的幫助。
如有不正確的地方請各位指出糾正。