畫江湖之 Redis持久化

Luson發表於2021-09-30

redis持久化

Redis 提供兩種持久化解決方案:RDB 持久化和 AOF 持久化

RDB 持久化:

可以在指定時間間隔內,生成資料集在這個時間點的快照;
採用 RDB 持久化方案時,Redis 會每隔一段時間對資料集進行快照備份,換句話說這種方案在伺服器發生故障時可能造成資料的丟失。所以,如果對資料的完整性有比較強烈的要求,可能不太適用這種備份方案,即它適用於做資料的備份;
RDB 持久化策略

  • 自動執行 RDB 持久化
    可以通過配置 redis.windows.conf 配置檔案來完成

Redis 高階
這裡的 save 指令表示「在 x 秒內有 n 個及以上鍵被改動」則會自動儲存一次資料集,比如配置中的 save 60 10000 表示如果在 60 秒內有 10000 個及以上的鍵被改動時則執行儲存資料集操作。
我們在啟動 Redis 服務時,伺服器會讀取配置檔案中的配置,所以 RDB 持久化策略會自動啟 動,當滿足條件時會執行持久化處理

  • 手動執行 RDB 持久化
    ,我們可以使用 SAVE 或 BGSAVE 命令 來手動執行 RDB 持久化處理。
    雖然,savebgsave 都可以手動的執行 RDB 持久化處理。但是它們的工作模式完全不同。
    • 執行 SAVE 命令時,會阻塞 Redis 主程式,直到儲存完成為止。在主程式阻塞期間,伺服器不能處理客戶端的任何請求
    • BGSAVE 則 fork 出一個子程式,子程式負責執行儲存處理,並在儲存完成之後向主程式傳送訊號,通知主程式儲存完成。所以 Redis 伺服器在 BGSAVE 執行期間仍然可以繼續處理客戶端的請求
      注意:雖然通過 SAVE 命令可以執行 RDB 持久化處理,但是它的執行原理同自動持久化中的 save 指令是完全不同的,save 指令的工作原理同 BGSAVE 指令。

優點

  • RDB 是一個非常緊湊(compact)的檔案(筆者注:因為 RDB 持久化檔案 dump.rdb 將資料集以二級制形式儲存),它儲存了 Redis 在某個時間點上的資料集。 這種檔案非常適合用於進行備份。
  • RDB 非常適用於災難恢復(disaster recovery):它只有一個檔案,並且內容都非常緊湊,可以(在加密後)將它傳送到別的資料中心。
  • RDB 可以最大化 Redis 的效能:父程式在儲存 RDB 檔案時唯一要做的就是 fork 出一個子程式,然後這個子程式就會處理接下來的所有儲存工作,父程式無須執行任何磁碟 I/O 操作。
  • RDB 在恢復大資料集時的速度比 AOF 的恢復速度要快。

缺點

  • 可能在伺服器故障時導致資料丟失,因為 RDB 採用的是定時儲存資料的機制,所以可能導致下次儲存資料時的資料丟失。
  • 可能導致伺服器無法處理客戶端處理,這是由於 RDB 執行非阻塞(BGSAVE 或 save 指令)儲存時,會 fock 出子程式,如果待儲存的資料集非常大可能會非常耗時。

AOF 持久化:

AOF(append only file):只進行追加操作的檔案。預設情況下,Redis 會禁用 AOF 重寫,如需開啟我們需要到配置檔案中將 appendonly 指令配置為 yes(預設:no 不啟用)

啟用 AOF 持久化方案後,當我們執行類似 SET 設定(或修改)命令時,Redis 會將命令以 Redis 通訊協議 文字儲存到 appendonly.aof 檔案中。

aof持久化策略

AOF 持久化方案提供 3 種不同時間策略將資料同步到磁碟中,同步策略通過 appendfsync 指令完成:

  • everysec(預設):表示每秒執行一次 fsync 同步策略,效率上同 RDB 持久化差不多。由於每秒同步一次,所以伺服器故障時會丟失 1 秒內的資料。
  • always: 每個寫命令都會呼叫 fsync 進行資料同步,最安全但影響效能。
  • no: 表示 Redis 從不執行 fsync,資料將完全由核心控制寫入磁碟。對於 Linux 系統來說,每 30 秒寫入一次。

    使用是推薦採用預設的 everysec 每秒同步策略,兼顧安全與效率。

AOF 持久化的執行原理
  1. Redis 主程式執行 fork () 建立出子程式。
  2. 子程式開始將新 AOF 檔案的內容寫入到臨時檔案。
  3. 對於所有新執行的寫入命令,父程式一邊將它們累積到一個記憶體快取中,一邊將這些改動追加到現有 AOF 檔案的末尾: 這樣即使在重寫的中途發生停機,現有的 AOF 檔案也還是安全的。
  4. 當子程式完成重寫工作時,它給父程式傳送一個訊號,父程式在接收到訊號之後,將記憶體快取中的所有資料追加到新 AOF 檔案的末尾。
  5. 搞定!現在 Redis 原子地用新檔案替換舊檔案,之後所有命令都會直接追加到新 AOF 檔案的末尾。
優化 AOF 備份檔案

我們知道 AOF 的執行原理是不斷的將寫入的命令以 Redis 通訊協議的資料格式追加到 .aof 檔案末尾,這就會導致檔案的體積不斷增大。

如果所有的命令完全不同到沒有關係。

但是,如果命令處理類似計數器的功能,比如執行 100 次 INCR(incr counter)處理,AOF 檔案會儲存全部的 INCR 命令的執行記錄,但實際上我們知道這些處理的結果同 set counter 100 並無二致。這就導致我們的 .aof 多儲存了 99 條命令記錄。

這時,我們就可以使用 Redis 提供的 BGREWRITEAOF 重寫命令,將 AOF 檔案進行重寫優化。

現在我們通過 BGREWRITEAOF 命令對檔案進行重寫處理:

127.0.0.1:6380> BGREWRITEAOF
Background append only file rewriting started  
優點
  • 提供比 RDB 持久化方案更安全的資料,由於預設採用每秒進行持久化處理,所有即使伺服器重啟或當機,最多也就丟失 1 秒內的資料。
  • AOF 檔案有序地儲存了對資料庫執行的所有寫入操作, 這些寫入操作以 Redis 協議的格式儲存, 因此 AOF 檔案的內容非常容易被人讀懂, 對檔案進行分析(parse)也很輕鬆
缺點
  • 相比於 RDB 持久化,AOF 檔案會比 RDB 備份檔案大得多。
  • AOF 持久化的速度可能比 RDB 持久化速度慢。
  • AOF 在過去曾經發生過這樣的 bug : 因為個別命令的原因,導致 AOF 檔案在重新載入時,無法將資料集恢復成儲存時的原樣。 (舉個例子,阻塞命令 BRPOPLPUSH 就曾經引起過這樣的 bug 。) 測試套件裡為這種情況新增了測試: 它們會自動生成隨機的、複雜的資料集, 並通過重新載入這些資料來確保一切正常。 雖然這種 bug 在 AOF 檔案中並不常見, 但是對比來說, RDB 幾乎是不可能出現這種 bug 的。

Redis 資料恢復

通過前面的學習我們瞭解到 Redis 是如何執行 RDB 和 AOF 持久化處理的,現在我們簡單瞭解下 Redis 是如何恢復 RDB 或 AOF 備份中的資料。

我們知道 Redis 是一種記憶體型的 NoSQL 資料庫(或者說資料結構),當服務重啟或當機都會導致記憶體中的資料丟失。

所以,當 Redis 伺服器重啟或恢復時,它會進行讀取 RDB 或 AOF 檔案(如果存在的話)處理,將檔案中的資料重新載入記憶體實現資料恢復操作。

Redis 資料恢復採用兩套恢復方案:

  • 開啟 AOF 持久化方案時,優先採用 AOF 檔案進行資料恢復

這個很好理解,因為 AOF 持久化方案的資料儲存是秒級的,所以相對於 RDB 持久化資料更完整,所以在啟動 Redis 伺服器是,會在 AOF 啟用時有限載入 AOF 檔案進行資料還原。

  • 未開啟 AOF 持久化方案是,Redis 通過載入 RDB 檔案進行資料恢復

持久化配置選項

RDB 配置位於 SNAPSHOTTING 配置節點。

  • 開啟 / 關閉 RDB 持久化功能
  1. 嚴格來說 Redis 沒有提供類似 AOF 的 appendonly 指令來開啟 RDB 持久化功能,我們可以通過註釋掉 save 指令來關閉 RDB 備份方案。
#save 900 1
#save 300 10
#save 60 10000
  1. 或者使用 config set save “” 命令來關閉重寫,但是如果僅使用這條命令,僅在當前伺服器執行時生效,所以重啟伺服器依然從配置檔案讀取 RDB 重寫規則。如果想永久生效,可以執行 config rewrite 命令,將 config set save 命令結果寫入到配置檔案。執行完 config rewrite 命令後會直接刪除 redis.windows.conf 配置中的 save 指令。
  • 是否啟用壓縮

通過 rdbcompression 指令完成,預設 yes 進行壓縮。

  • 修改備份檔名

使用 dbfilename 指令,預設值 dump.rdb

  • 修改備份檔案儲存目錄

使用 dir 指令,預設值 your_redis_path。另外 AOF 備份資料同樣會儲存到該目錄下。

AOF 持久化配置選項

AOF 配置位於 APPEND ONLY MODE 配置節點。

  • 開啟 / 關閉 AOF 持久化功能

開啟 AOF 持久化功能,通過 appendonly 指令完成,取值範圍 yes / no,預設:no 不開啟 AOF 重寫。

  • 修改備份檔名

appendfilename 指令完成,預設值 appendonly.aof

  • 設定持久化執行策略

請參考前文 appendfsync 指令說明。

  • AOF 備份檔案重寫規則配置

之前我們通過使用命令 BGREWRITEAOF 對 AOF 執行重寫,但是當我們啟用 AOF 持久化功能後,Redis 預設會啟用 AOF 重寫優化,這個工作有兩條指令完成:

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

auto-aof-rewrite-percentage 指令表示,本次執行 AOF 重寫時,當 AOF 檔案的大小是上次執行重寫時檔案的百分之多少才可以自動重寫。預設: 100 表示本次重寫時的 AOF 檔案是上次 2 倍可以自動重寫。

auto-aof-rewrite-min-size 這個指令用於設定進行 AOF 檔案自動重寫的最小檔案大小。

換言之,這兩條配置表示:當 AOF 檔案大小達到 64mb 時,才開始自動進行重寫。下一次只有當檔案大小需達到 128 mb 才能再次重寫,以此類推。

  • 自動修復出錯的 AOF 資料

當我們的 Redis 伺服器當機時,可能導致 AOF 檔案的尾部資料不完整,在重啟 Redis 伺服器可能導致資料不一致。此時可以通過:

aof-load-truncated 指令在啟動 Redis 自動修復檔案。它的取值範圍是 yes / no,預設為 yes 重啟時自動修復。

同樣的我們也可以通過 redis-check-aof –fix 修復工具手動進行修復

本節參考資料 blog.phpzendo.com/?p=442

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章