對比 Redis 中 RDB 和 AOF 持久化

概念

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 文件來還原數據庫狀態。

http://cdn.chaohang.top/20200914084027.png

AOF 的載入

AOF 中包含了所有的寫命令,服務器只要讀入並重新執行一遍AOF文件裏保存的寫命令,就可以還原服務器關閉前的狀態。

Redis 讀取 AOF 文件並還原數據庫狀態的詳細步驟:

  1. 創建一個不帶網絡連接的僞客戶端:因爲 Redis 的命令只能在客戶端上下文中執行,而載入 AOF 文件時所使用的命令直接來源於 AOF 文件而不是網絡連接,所以用來還原數據的僞客戶端不需要網絡連接;
  2. 從 AOF 文件中分析並讀取出一條寫命令;
  3. 使用僞客戶端執行讀出的寫命令;
  4. 循環執行步驟2和步驟3,直到 AOF 文件中的所有命令都被執行。

資料

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

本文首發於我的個人博客 https://chaohang.top

作者張小超

轉載請註明出處

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章