Redis快照原理詳解


本文對Redis快照的實現過程進行介紹,了解Redis快照實現過程對Redis管理很有幫助。

Redis默認會將快照文件存儲在Redis當前進程的工作目錄中的dump.rdb文件中,可以通過配置dir和dbfilename兩個參數分別指定快照文件的存儲路徑和文件名。快照的過程如下。


(1)Redis使用fork函數復制一份當前進程(父進程)的副本(子進程);
(2)父進程繼續接收並處理客戶端發來的命令,而子進程開始將內存中的數據寫入硬盤中的臨時文件;
(3)當子進程寫入完所有數據后會用該臨時文件替換舊的 RDB 文件,至此一次快照操作完成。


在執行 fork 的時候操作系統(類 Unix 操作系統)會使用寫時復制(copy-on-write)策略,即fork函數發生的一刻父子進程共享同一內存數據,當父進程要更改其中某片數據時(如執行一個寫命令),操作系統會將該片數據復制一份以保證子進程的數據不受影響,所以新的RDB文件存儲的是執行fork一刻的內存數據。


寫時復制策略也保證了在 fork 的時刻雖然看上去生成了兩份內存副本,但實際上內存的占用量並不會增加一倍。這就意味着當系統內存只有2 GB,而Redis數據庫的內存有1.5 GB時,執行 fork后內存使用量並不會增加到3 GB(超出物理內存)。為此需要確保 Linux 系統允許應用程序申請超過可用內存(物理內存和交換分區)的空間,方法是在/etc/sysctl.conf 文件加入 vm.overcommit_memory = 1,然后重啟系統或者執行 sysctl vm.overcommit_memory=1 確保設置生效。


另外需要注意的是,當進行快照的過程中,如果寫入操作較多,造成 fork 前后數據差異較大,是會使得內存使用量顯著超過實際數據大小的,因為內存中不僅保存了當前的數據庫數據,而且還保存着 fork 時刻的內存數據。進行內存用量估算時很容易忽略這一問題,造成內存用量超限。


通過上述過程可以發現Redis在進行快照的過程中不會修改RDB文件,只有快照結束后才會將舊的文件替換成新的,也就是說任何時候 RDB 文件都是完整的。這使得我們可以通過定時備份 RDB 文件來實現 Redis 數據庫備份。RDB 文件是經過壓縮(可以配置rdbcompression 參數以禁用壓縮節省CPU占用)的二進制格式,所以占用的空間會小於內存中的數據大小,更加利於傳輸。


Redis啟動后會讀取RDB快照文件,將數據從硬盤載入到內存。根據數據量大小與結構和服務器性能不同,這個時間也不同。通常將一個記錄1000萬個字符串類型鍵、大小為1 GB 的快照文件載入到內存中需要花費20~30秒。


通過RDB方式實現持久化,一旦Redis異常退出,就會丟失最后一次快照以后更改的所有數據。這就需要開發者根據具體的應用場合,通過組合設置自動快照條件的方式來將可能發生的數據損失控制在能夠接受的范圍。例如,使用Redis存儲緩存數據時,丟失最近幾秒的數據或者丟失最近更新的幾十個鍵並不會有很大的影響。如果數據相對重要,希望將損失降到最小,則可以使用AOF方式進行持久化。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM