因為 Redis 是記憶體資料庫,它將自己的資料儲存在記憶體裡面,所以如果不想辦法將儲存在記憶體中的資料庫狀態儲存到磁碟裡面,那麼一旦伺服器程式退出,伺服器中的資料也將會丟失,為了解決這個問題,Redis 提供了持久化的功能。
Redis 中的持久化有兩種,分別是 RDB 和 AOF。
RDB 持久化
RDB 是將 Redis 記憶體中的快照直接儲存到磁碟中,避免資料丟失。
RDB 檔案的建立
RDB 檔案是一個經過壓縮的二進位制檔案。有兩個命令可以生產 RDB 檔案,一個是 SAVE,另一個是 BGSAVE。
SAVE 命令會阻塞 Redis 伺服器程式,直到 RDB 檔案建立完畢為止,在伺服器程式阻塞期間,伺服器不能處理任何命令請求。
BGSAVE 命令會派生出一個子程式,然後由子程式負責建立 RDB 檔案,伺服器程式(父程式)繼續處理命令請求。
除了主動執行命令之外,Redis 還可以根據配置自動進行 RDB 持久化。如果我們向伺服器有如下配置(預設就有):
save 900 1
save 300 10
save 60 10000
那麼只要滿足以下三個條件中的任意一個,BGSAVE 命令就會被執行:
- 伺服器在 900 秒之內,對資料庫進行了至少 1 次修改。
- 伺服器在 300 秒之內,對資料庫進行了至少 10 次修改。
- 伺服器在 60 秒之內,對資料庫進行了至少 10000 次修改。
RDB 檔案的載入
RDB 檔案的載入工作是在伺服器啟動時自動執行的,所以 Redis 並沒有專門用於載入 RDB 檔案的命令,只要 Redis 伺服器在啟動時檢查到 RDB 檔案,就會自動載入。
另外值得一提的是,因為 AOF 檔案的更新頻率通常比 RDB 檔案的更新頻率高,所以:
- 如果伺服器開啟了 AOF 持久化功能,那麼伺服器會優先使用 AOF 檔案來還原資料庫狀態。
- 只有在 AOF 持久化功能處於關閉狀態時,伺服器才會使用 RDB 檔案來還原資料庫狀態。
如下圖所示(出自《Redis設計與實現第二版》第十章:RDB持久化):
AOF 持久化
和 RDB 持久化不同,AOF 持久化是通過儲存 Redis 伺服器所執行的謝明令來記錄資料庫狀態的,如下圖所示(出自《Redis設計與實現第二版》第十一章:AOF持久化):
AOF 持久化的實現
當 AOF 持久化功能處於開啟狀態時,伺服器在執行完一個寫命令之後,會講被執行的寫命令追加到伺服器狀態的 aof_buf 緩衝區的末尾。
Redis 伺服器會每隔 100ms 將 aof_buf 緩衝區的內容真正寫入到 AOF 檔案裡面。
AOF 持久化的效率和安全性
伺服器配裡 appendfsync 選項的值直接決定 AOF 持久化功能的效率和安全性。
- 當 appendfsyn 的值為 always 時,伺服器在每個事件迴圈都要將 aof_buf 緩衝區中的所有內容寫入到 AOF 檔案,並且同步 AOF 檔案,所以 always 的效率是 aPPendfsync 選項三個值當中最慢的一個,但從安全性來說, always 也是最安全的,因為即使出現故障停機, AOF 持久化也只會丟失一個事件迴圈中所產生的命令資料。
- 當 appendfsync 的值為 everysec 時,伺服器在每個事件迴圈都要將 aof_buf 緩衝區中的所有內容寫入到 AOF 檔案,並且每隔一秒就要在子執行緒中對 AOF 檔案進行一次同步。從效率上來講, everysec 模式足夠快,並且就算出現故障停機,資料庫也只丟失一秒鐘的命令資料。
- 當 appendfsync 的值為 no 時,伺服器在每個事件迴圈都要將 aof_buf 緩衝區中的所有內容寫入到 AOF 檔案,至於何時對 AOF 檔案進行同步,則由作業系統控制。因為處於 no 模式下的 flushAppendonlyFile 呼叫無須執行同步操作,所以該模式下的 AOF 檔案寫入速度總是最快的,不過因為這種模式會在系統快取中積取一段時間的寫入資料,所以該模式的單次同步時長通常是三種模式中時間最長的。從平攤操作的角度來看, no 模式和 everysec 模式的效率類似,當出現故障停機時,使用 no 模式的伺服器將丟失上次同步 AOF 檔案之後的所有寫命令資料。
AOF 檔案的載入與資料還原
因為 AOF 檔案裡面包含了重建資料庫狀態所需的所有寫命令, 所以伺服器只要讀入並重新執行一遍 AOF 檔案裡面儲存的寫命令,就可以還原伺服器關閉之前的資料庫狀態。
AOF 檔案載入過程如下(出自《Redis設計與實現第二版》第十一章:AOF持久化):
AOF 檔案的重寫
因為 AOF 持久化是通過儲存被執行的寫命令來記錄資料庫狀態的,所以隨著伺服器執行時間的流逝, AOF 檔案中的內容會越來越多,檔案的體積也會越來越大,如果不加以控制的話,體積過大的 AOF 檔案很可能對 Redis 伺服器、甚至整個宿主計算機造成影響,並且 AOF 檔案的體積越大,使用 AOF 檔案來進行資料還原所需的時間就越多。
為了解決 AOF 檔案體積過大的問題,Redis 提供了 AOF 檔案重寫功能。即伺服器可以建立一個新的 AOF 檔案來代替現有的 AOF 檔案,但由於新的 AOF 檔案不會包含任何浪費空間的冗餘命令(即只有寫命令,沒有del命令等),所以新 AOF 檔案的體積通常比舊 AOF 檔案的體積小得多。