對比 Redis 中 RDB 和 AOF 持久化

超超不會飛發表於2020-09-16

概念

Redis 是記憶體資料庫,資料儲存在記憶體中,一旦伺服器程式退出,資料就丟失了,所以 Redis 需要想辦法將儲存在記憶體中的資料持久化到磁碟。

Redis 提供了兩種持久化功能:

  1. RDB (Redis Database):生成 RDB 檔案,儲存的是 key-value 的形式。
  2. AOF (Append Only File):儲存 Redis 執行過程中的寫命令。

生成

RDB 的生成

  1. SAVE 命令會阻塞 Redis 服務程式,直到 RDB 檔案建立完畢為止,在伺服器程式阻塞期間,伺服器不能處理任何命令請求。

  2. BGSAVE 命令會派生出一個子程式,然後由子程式負責建立 RDB 檔案,伺服器程式(父程式)繼續處理命令請求。

如果兩個 key 值的修改具有事務性,需要手動加事務,不然備份時可能會導致兩個值不一致。

除了主動執行命令,我們還可以通過 save 選項設定多個儲存條件,只要任意一個條件滿足,伺服器就會執行 BGSAVE 命令:

save 900 1
save 300 10
save 60 10000

那麼只要滿足以下三個條件中的任意一個,BGSAVE 命令就會被執行:

  1. 伺服器在900秒之內,對資料庫進行了至少1次修改。
  2. 伺服器在300秒之內,對資料庫進行了至少10次修改。
  3. 伺服器在60秒之內,對資料庫進行了至少10000次修改。

AOF 的生成

只要開啟 AOF 持久化功能,伺服器在執行完一個寫命令後,會以協議格式將被執行的寫命令追加到伺服器狀態的 aof_buf 緩衝區的末尾。

現代作業系統中,使用者在寫檔案時,作業系統通常會將寫入資料暫時儲存在一個記憶體緩衝區裡面,等到緩衝區被填滿,或者超過了指定時限之後,才真正將緩衝區中的資料寫入磁碟。這就有可能導致緩衝區內的資料還未寫入磁碟,計算機發生停機,導致資料丟失。

appendfsync 選項的值可以決定 AOF 持久化功能的效率和安全性:

  1. always 每次都同步到磁碟,效率低,安全性高;
  2. everysec 每隔一秒同步到磁碟,效率足夠快,安全性高,只丟失一秒的資料;
  3. no 由作業系統控制同步到磁碟的時機,速度最快,安全性最低。

AOF 的重寫

因為 AOF 儲存的是寫命令,隨著伺服器的執行,同一個鍵值被操作的次數越多,單個鍵值就會產生多條寫命令,AOF 檔案就會越大,還原的時間就會越久。

為了解決 AOF 體積膨脹的問題,Redis 提供了 AOF 檔案重寫(rewrite)功能。

AOF 重寫並不是對舊的 AOF 檔案進行壓縮。Redis 會從資料庫中讀出資料,生成對應的寫命令,並寫入新的 AOF 檔案中,當新的 AOF 檔案重寫了所有資料的寫命令,就可以替換掉舊 AOF 檔案。

AOF 重寫可以在後臺進行,在重寫過程中新產生的資料,會寫入 AOF 重寫緩衝區中,當重寫結束再把緩衝區的寫命令追加到新的 AOF 檔案中即可。

載入

RDB 的載入

RDB 檔案的載入工作是在伺服器啟動時自動執行的,所以 Redis 沒有專門用於載入的命令。

因為 AOF 檔案的更新頻率通常比 RDB 檔案的更新頻率高,所以:

  1. 如果伺服器啟動了AOF 持久化功能,那麼伺服器會優先使用 AOF 檔案來還原資料庫狀態。
  2. 只有在 AOF 持久化功能處於關閉狀態時,伺服器才會使用 RDB 檔案來還原資料庫狀態。

https://i.iter01.com/images/8ef0c13d2d5299473ea7838507bf3ee2a207efd3c5008330cf34479e3086296a.png

AOF 的載入

AOF 中包含了所有的寫命令,伺服器只要讀入並重新執行一遍AOF檔案裡儲存的寫命令,就可以還原伺服器關閉前的狀態。

Redis 讀取 AOF 檔案並還原資料庫狀態的詳細步驟:

  1. 建立一個不帶網路連線的偽客戶端:因為 Redis 的命令只能在客戶端上下文中執行,而載入 AOF 檔案時所使用的命令直接來源於 AOF 檔案而不是網路連線,所以用來還原資料的偽客戶端不需要網路連線;
  2. 從 AOF 檔案中分析並讀取出一條寫命令;
  3. 使用偽客戶端執行讀出的寫命令;
  4. 迴圈執行步驟2和步驟3,直到 AOF 檔案中的所有命令都被執行。

資料

Redis設計與實現-黃健巨集-微信讀書

本文首發於我的個人部落格 https://chaohang.top

作者張小超

轉載請註明出處

歡迎關注我的微信公眾號 【超超不會飛】,獲取第一時間的更新。

相關文章