Redis的強勁性能很大程度上是由于其將所有資料都存盤在了記憶體中,然而當Redis重啟 后,所有存盤在記憶體中的資料就會丟失,
在一些情況下,我們會希望 Redis 在重啟后能夠保 證資料不丟失,例如:
- 將Redis作為資料庫使用時,
- 將 Redis 作為快取服務器,但快取被穿透后會對性能造成較大影響,所有快取同時 失效會導致快取雪崩,從而使服務無法回應,
這時我們希望 Redis 能將資料從記憶體中以某種形式同步到硬碟中,使得重啟后可以根據 硬碟中的記錄恢復資料,這一程序就是持久化,
Redis支持兩種方式的持久化,一種是RDB方式,另一種是AOF方式,前者會根據指定的規則
“定時”將記憶體中的資料存盤在硬碟上,而后者在每次執行命令后將命令本身記錄下來, 兩種持久化方式可以單獨使用其中一種,但更多情況下是將二者結合使用,
一、概述
RDB方式的持久化是通過快照(snapshotting)完成的,當`符合一定條件時Redis會自動將 記憶體中的所有資料生成一份副本并存盤在硬碟上,這個程序即為“快照”,
Redis會在以下幾種 情況下對資料進行快照:
- 根據配置規則進行自動快照;
- 用戶執行 SAVE或 BGSAVE命令;
- 執行 FLUSHALL命令;
- 執行復制(replication)時,
save 900 1
save 300 10
save 60 10000
每條快照條件占一行,并且以 save 引數開頭,同時可以存在多個條件,條件之間 是“或”的關系,就這個例子而言,save 900 1 的意思是在 15 分鐘(900 秒)內有一個或一個 以上的鍵被更改則進行快照,同理,save 300 10表示在300秒內至少有10個鍵被修改則進行快 照,
二、根據配置規則進行自動快照
Redis允許用戶自定義快照條件,當符合快照條件時,Redis會自動執行快照操作,
進行快照的條件可以由用戶在組態檔中自定義,由兩個引數構成:時間視窗M和改動的鍵的個數N,每當時間M內被更改的鍵的個數大于N時,即符合自動快照條件,例如Redis安裝目錄 中包含的樣例組態檔中預置的3個條件:
三、用戶執行 SAVE或 BGSAVE命令
除了讓 Redis 自動進行快照外,當進行服務重啟、手動遷移以及備份時我們也會需要手 動執行快照操作,Redis提供了兩個命令來完成這一任務,
- SAVE命令
當執行SAVE命令時,Redis同步地進行快照操作,在快照執行的程序中會阻塞所有來自 客戶端的請求,當資料庫中的資料比較多時,這一程序會導致Redis較長時間不回應,所以要盡量避免在生產環境中使用這一命令, - BGSAVE命令
需要手動執行快照時推薦使用 BGSAVE 命令,BGSAVE 命令可以在后臺異步地進行快照操作,快照的同時服務器還可以繼續回應來自客戶端的請求,執行 BGSAVE后Redis會立即 回傳 OK表示開始執行快照操作,如果想知道快照是否完成,可以通過LASTSAVE命令獲取最近一次成功執行快照的時間,回傳結果是一個Unix時間戳,如:
redis> LASTSAVE
(integer) 1423537869
四、執行 FLUSHALL命令
當執行 FLUSHALL 命令時,Redis 會清除資料庫中的所有資料,需要注意的是,不論清空資料庫的程序是否觸發了自動快照條件,只要自動快照條件不為空,Redis就會執行一次快照操作,
例如,當定義的快照條件為當1秒內修改10 000個鍵時進行自動快照,而當資料庫里 只有一個鍵時,執行FLUSHALL命令也會觸發快照,即使這一程序實際上只有一個鍵被修改了,
當沒有定義自動快照條件時,執行FLUSHALL則不會進行快照,
五、執行復制時
當設定了
主從模式時,Redis 會在復制初始化時進行自動快照,
這里只需要了解當使用復制操作時,即使沒有定義自動快照條 件,并且沒有手動執行過快照操作,也會生成RDB快照檔案,
六、快照原理
理清Redis實作快照的程序對我們了解快照檔案的特性有很大的幫助,Redis默認會將快 照檔案存盤在Redis當前行程的作業目錄中的dump.rdb檔案中,可以通過配置
dir和dbfilename兩個引數分別指定快照檔案的存盤路徑和檔案名,
快照的程序如下:
- Redis使用fork函式復制一份當前行程(父行程)的副本(子行程);
- 父行程繼續接收并處理客戶端發來的命令,而子行程開始將記憶體中的資料寫入硬碟中的臨時檔案;
- 當子行程寫入完所有資料后會用該臨時檔案替換舊的 RDB 檔案,至此一次快照操作完成,
提示 在執行 fork的時候作業系統(類 Unix 作業系統)會使用寫時復制(copy -on- write)策略,即fork函式發生的一刻父子行程共享同一記憶體資料,當父行程要更改其中某片 資料時(如執行一個寫命令),作業系統會將該片資料復制一份以保證子行程的資料不受影 響,所以新的RDB檔案存盤的是執行fork一刻的記憶體資料,
寫時復制策略也保證了在 fork的時刻雖然看上去生成了兩份記憶體副本,但實際上記憶體的 占用量并不會增加一倍,這就意味著當系統記憶體只有2 GB,而Redis資料庫的記憶體有1.5 GB 時,執行 fork后記憶體使用量并不會增加到3 GB(超出物理記憶體),為此需要確保 Linux 系統 允許應用程式申請超過可用記憶體(物理記憶體和交換磁區)的空間,方法是在
/etc/sy sctl.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方式進行持久化,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/261351.html
標籤:其他
上一篇:爬蟲架構設計
下一篇:解決telnet: connect to address 127.0.0.1: Connection refused的錯誤資訊問題
