Redis資料持久化方式RDB和AOF的區別
Redis官方提供了兩種資料持久化的方式,分別是:RDB和AOF。今天我們來討論一下這兩種持久化方式的區別。
RDB
基本原理:RDB持久化主要是通過SAVE和BGSAVE兩個命令對Redis資料庫中當前的資料做snapshot並生成rdb檔案來實現的。其中SAVE是阻塞的,BGSAVE是非阻塞的,通過fork了一個子程序來完成的。在Redis啟動的時候會檢測rdb檔案,然後載入rdb檔案中未過期的資料到伺服器中
配置資訊:RDB可以通過向伺服器提供配置資訊來自動間隔性儲存。如預設情況下伺服器滿足以下3個條件中任意一個條件就會觸發BGSAVE命令
save 900 1 // 伺服器在900秒之內,對資料庫進行了至少1次修改 save 300 10 // 伺服器在300秒之內,對資料庫進行了至少10次修改 save 60 10000 // 伺服器在60秒之內,對資料庫進行了至少10000次修改
實現方式:伺服器通過維護dirty
計數器和lastsave
屬性分別記錄距離上次成功執行SAVE或者BGSAVE命令之後,伺服器對資料庫狀態進行修改的次數和最後一次成功SAVE或者BGSAVE的UNIX時間戳。由Redis週期性操作函式serverCron
預設每隔100ms
來檢測是否滿足配置資訊中的要求,然後再決定是否執行SAVE或者BGSAVE命令來對資料庫進行備份。
AOF
基本原理:AOF(Append Only File)持久化是通過將儲存每次執行的客戶端命令,然後由一個偽客戶端來執行這些命令將資料寫入到伺服器中的方式實現的。一共分為命令追加(append)、檔案寫入、檔案同步(sync)
命令追加
當有修改、刪除操作時,伺服器會在執行完之後以協議格式將被執行的寫命令追加到伺服器狀態的aof_buf
緩衝區的末尾
檔案寫入
Redis的服務程序就是一個事件迴圈,這個迴圈中的檔案事件負責接收客戶端的命令請求。伺服器在處理檔案事件時可能會執行寫命令,同時會追加到aof_buf
緩衝區,所以在每結束一次迴圈之前,都會呼叫flushAppendOnlyFile
函式,將aof_buf
緩衝區的資料寫入到AOF檔案裡面。
檔案同步
flushAppendOnlyFile
函式通過伺服器配置appendfsync
選項的值來決定的將每次迴圈結束之前aof_buf
緩衝區的資料寫入到AOF檔案後,將以何種方式同步到AOF檔案裡面:
appendfsync | flushAppendOnlyFile函式的行為 |
---|---|
always |
每次都同步 |
everysec |
單獨一個執行緒一分鐘同步一次 |
no |
作業系統決定何時同步 |
AOF重寫
AOF方式持久化時記錄的時一條一條的寫命令,隨著伺服器執行的時間越來越長,AOF檔案會越來越大,AOF重寫就是為了解決這個問題。
函式aof_rewrite
啟動一個子程序建立AOF重寫緩衝區,將Redis中所有的資料生成多條寫命令寫入AOF檔案。在子程序進行AOF重寫期間,伺服器還會處理寫請求的命令,這會導致伺服器當前的資料庫狀態和重寫後的AOF檔案所儲存的資料不一致。為了解決這個問題,子程序在執行AOF重寫期間,伺服器程序需要執行以下三件事情:
- 執行客戶端傳送來的命令
- 將執行後的寫命令追加到AOF緩衝區
- 將執行後的寫命令追加到AOF重寫緩衝區
當子程序完成AOF重寫工作後,會發送一個訊號到父程序,父程序收到訊號後會呼叫訊號處理函式(這個過程會block主父程序),執行以下工作:
- 將AOF重寫緩衝區中的資料全部寫入到新AOF檔案中,這時新AOF檔案所儲存的資料庫狀態和伺服器當前的資料庫狀態一致
- 對新的AOF檔案進行改名,原子的覆蓋現有的AOF檔案,完成新舊兩個AOF檔案的替換
RDB與AOF區別
- RDB可以理解為是一種全量資料更新機制,AOF可以理解為是一種增量的更新機制,AOF重寫可以理解為是一種全量+增量的更新機制(第一次是全量,後面都是增量)
- RDB適合伺服器資料庫資料量小,寫命令頻繁的場景
- AOF適合資料量大,寫命令少的場景
- AOF重寫適合在AOF運行了很久的寫命令之後執行