redis持久化(RDB、AOF、混合持久化)


redis持久化(RDB、AOF、混合持久化)

  • 1. RDB快照(snapshot)

在默認情況下, Redis 將內存數據庫快照保存在名字為 dump.rdb 的二進制文件中。

你可以對 Redis 進行設置, 讓它在“N 秒內數據集至少有 M 個改動”這一條件被滿足時,
自動保存一次數據集。

比如說, 以下設置會讓 Redis 在滿足“60 秒內有至少有 1000 個鍵被改動”這一條件時,
自動保存一次數據集:

save 60 1000

優點:

  1. RDB 是一個非常緊湊(compact)的文件,體積小,因此在傳輸速度上比較快,因此適合災難恢復。

  2. RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快得多。

缺點:

  1. RDB是一個快照過程,無法完整的保存所以數據,尤其在數據量比較大時候,一旦出現故障丟失的數據將更多。

  2. RDB文件是特定的格式,閱讀性差,由於格式固定,可能存在不兼容情況。


  • 2. AOF(append-only file)

快照功能並不是非常耐久(durable): 如果 Redis 因為某些原因而造成故障停機, 那么服務器將丟失最近寫入、且仍未保存到快照中的那些數據。從 1.1 版本開始, Redis 增加了一種完全耐久的持久化方式: AOF 持久化,將修改的每一條指令記錄進文件

你可以通過修改配置文件來打開 AOF 功能:

appendonly yes

從現在開始, 每當 Redis 執行一個改變數據集的命令時(比如 SET), 這個命令就會被追加到 AOF 文件的末尾。

這樣的話, 當 Redis 重新啟動時, 程序就可以通過重新執行 AOF 文件中的命令來達到重建數據集的目的。

你可以配置 Redis 多久才將數據 fsync 到磁盤一次。

有三個選項:

  • appendfsync always。每次有新命令追加到 AOF 文件時就執行一次 fsync :非常慢,也非常安全。
  • appendfsync everysec。每秒 fsync 一次:足夠快(和使用 RDB 持久化差不多),並且在故障時只會丟失 1 秒鍾的數據。
  • appendfsync no。從不 fsync :將數據交給操作系統來處理。更快,也更不安全的選擇。

推薦(並且也是默認)的措施為每秒 fsync 一次, 這種 fsync 策略可以兼顧速度和安全性。

優點:

  1. 數據更完整,秒級數據丟失(取決於設置fsync策略)。、

  2. 兼容性較高,由於是基於redis通訊協議而形成的命令追加方式,無論何種版本的redis都兼容。

  3. aof文件是明文的,可閱讀性較好。

缺點:

  1. 數據文件體積較大,即使有重寫機制,但是在相同的數據集情況下,AOF文件通常比RDB文件大。

  2. 相對RDB方式,AOF速度慢於RDB,並且在數據量大時候,恢復速度AOF速度也是慢於RDB。

  3. 由於頻繁地將命令同步到文件中,AOF持久化對性能的影響相對RDB較大。


  • AOF重寫

aof 文件記錄的是每一條redis命令,有時候我們會對某一個key進行多次set,中間會產生很多條命令,但是結果只有一個。

set name 1
...
set name 12
set name 123
...
set name 1234
set name 12345

例如我們執行了上述命令,aof 文件會記錄着每一條命令。在redis重啟時,會逐條執行上述的命令。但是其實可以精簡為set name 12345,其余的幾條命令其實沒有意義。AOF重寫就是實現了這個功能。

相關配置:

auto-aof-rewrite-percentage 100  # 指當前aof文件比上次重寫的增長比例大小,達到這個大小就進行 aof 重寫
auto-aof-rewrite-min-size 64mb  # 最開始aof文件必須要達到這個文件時才觸發,后面的每次重寫就不會根據這個變量了

以上配置的意思是:

在 aof 文件小於64mb的時候不進行重寫,當到達64mb的時候,就重寫一次。重寫后的 aof 文件可能是10mb。上面配置了auto-aof-rewrite-percentage 100,即 aof 文件到了20mb的時候,又開始重寫一次。以此類推。

AOF 是在后台自動重寫(redis會fork一個子進程來進行備份,保證主進程不會阻塞),也可以人為執行命令 bgrewriteaof 重寫 AOF。


  • 使用子進程來進行AOF重寫時會遇到的問題

問題:

子進程在進行AOF重寫期間,服務器進程還要繼續處理命令請求,而新的命令可能對現有的數據進行修改,這會讓當前數據庫的數據和重寫后的AOF文件中的數據不一致。

解決方案:

要知道redis是怎么處理這個問題的,需要先了解下AOF重寫的具體實現:

AOF文件重寫過程與RDB快照bgsave工作過程有點相似,都是通過fork子進程,由子進程完成相應的操作,同樣的在fork子進程簡短的時間內,redis是阻塞的。

(1)開始bgrewriteaof,判斷當前有沒有bgsave命令(RDB持久化)/bgrewriteaof在執行,倘若有,則這些命令執行完成以后在執行。

(2)主進程fork出子進程,在這一個短暫的時間內,redis是阻塞的。

(3)主進程fork完子進程繼續接受客戶端請求。此時,客戶端的寫請求不僅僅寫入aof_buf緩沖區,還寫入aof_rewrite_buf重寫緩沖區。一方面是寫入aof_buf緩沖區並根據appendfsync策略同步到磁盤,保證原有AOF文件完整和正確。另一方面寫入aof_rewrite_buf重寫緩沖區,保存fork之后的客戶端的寫請求,防止新AOF文件生成期間丟失這部分數據。

(4.1)子進程寫完新的AOF文件后,向主進程發信號,父進程更新統計信息。

(4.2)主進程把aof_rewrite_buf中的數據寫入到新的AOF文件。

(5.)使用新的AOF文件覆蓋舊的AOF文件,標志AOF重寫完成。


  • Redis 4.0 混合持久化

重啟 Redis 時,我們很少使用 rdb 來恢復內存狀態,因為會丟失大量數據。

如果使用 AOF 日志重放,性能則相對 rdb 來說要慢很多,這樣在 Redis 實例很大的情況下,啟動的時候需要花費很長的時間。

Redis 4.0 為了解決這個問題,帶來了一個新的持久化選項——混合持久化。

混合持久化同樣也是通過bgrewriteaof完成的,不同的是當開啟混合持久化時,fork出的子進程先將共享的內存副本全量的以RDB方式寫入aof文件,然后在將aof_rewrite_buf重寫緩沖區的增量命令以AOF方式寫入到文件,寫入完成后通知主進程更新統計信息,並將新的含有RDB格式和AOF格式的AOF文件替換舊的的AOF文件。簡單的說:新的AOF文件前半段是RDB格式的全量數據后半段是AOF格式的增量數據,如下圖:

在redis重啟的時候,加載 aof 文件進行恢復數據:先加載 rdb 內容再加載剩余的 aof。

混合持久化配置:

aof-use-rdb-preamble yes  # yes:開啟,no:關閉

  • RDB和AOF,應該用哪一個?

如果你可以承受數分鍾以內的數據丟失, 那么你可以只使用 RDB 持久化。

有很多用戶都只使用 AOF 持久化, 但我們並不推薦這種方式: 因為定時生成 RDB 快照(snapshot)非常便於進行數據庫備份, 並且 RDB 恢復數據集的速度也要比 AOF 恢復的速度要快。如果只用AOF持久化,數據量很大時,在redis啟動的時候需要花費大量的時間。

如果你非常關心你的數據,建議使用 redis 4.0 以后的混合持久化特性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM