快速掌握Redis——第六招:持久化 (數據備份與恢復)

1 何爲持久化

redis 是內存數據庫,掉電會丟失,轉移數據不便。持久化就是內存數據到硬盤數據的轉化。 固然,也能夠硬盤到內存(備份的概念,保存,恢復)。redis

2 怎麼實現

兩種方法:快照方式(rdb)+日誌方式(aof) 快速+最大化redis性能+方便:rdb 模式 更持久:aof 模式 建議:合理的同時使用這兩種方式。數據庫

2.1 rdb 快照模式

  • Snapshotting (快照) 語法

快照是默認的持久化方式(內存全拷貝)。這種方式是就是將內存中數據以快照的方式寫入到二進制文件中,默認的文件名爲dump.rdb。能夠經過配置設置自動作快照持久 化的方式。咱們能夠配置redis在n秒內若是超過m個key被修改就自動作快照,下面是默認的快照保存配置。(建議從下往上看,60s-300s-900s)緩存

save 900 1  //900秒內若是超過1個key被修改,則發起快照保存
    save 300 10 //300秒內容如超過10個key被修改,則發起快照保存
    save 60 10000 
     //(這3個選項都屏蔽,則rdb禁用)
    
    stop-writes-on-bgsave-error yes  // 後臺備份進程出錯時,主進程停不中止寫入
    rdbcompression yes    // 導出的rdb文件是否壓縮
    Rdbchecksum   yes //  導入rbd恢復時數據時,要不要檢驗rdb的完整性
    dbfilename dump.rdb  //導出來的rdb文件名
    dir ./  //rdb的放置路徑
  • 詳細的快照保存過程

1.redis調用fork,如今有了子進程和父進程。app

2.父進程繼續處理client請求,子進程負責將內存內容寫入到臨時文件。因爲os的寫時複製機制(copy on write)父子進程會共享相同的物理頁面,當父進程處理寫請求時os會爲父進程要修改的頁面建立副本,而不是寫共享的頁面。因此子進程的地址空間內的數 據是fork時刻整個數據庫的一個快照。函數

3.當子進程將快照寫入臨時文件完畢後,用臨時文件替換原來的快照文件,而後子進程退出。性能

client 也可使用save或者bgsave命令通知redis作一次快照持久化。save操做是在主線程中保存快照的,因爲redis是用一個主線程來處理全部 client的請求,這種方式會阻塞全部client請求。因此不推薦使用。另外一點須要注意的是,每次快照持久化都是將內存數據完整寫入到磁盤一次,並非增量的只同步增長數據。若是數據量大的話,並且寫操做比較多,必然會引發大量的磁盤io操做,可能會嚴重影響性能。優化

另外因爲快照方式是在必定間隔時間作一次的,因此若是redis意外down掉的話,就會丟失最後一次快照後的全部修改。若是應用要求不能丟失任何修改的話,能夠採用aof持久化方式。操作系統

2.2 aof 日誌模式

aof 比快照方式有更好的持久化性,是因爲在使用aof持久化方式時,redis會將每個收到的寫命令都經過write函數追加到文件中(默認是 appendonly.aof)。當redis重啓時會經過從新執行文件中保存的寫命令來在內存中重建整個數據庫的內容。固然因爲os會在內核中緩存 write作的修改,因此可能不是當即寫到磁盤上。這樣aof方式的持久化也仍是有可能會丟失部分修改。不過咱們能夠經過配置文件告訴redis咱們想要 經過fsync函數強制os寫入到磁盤的時機。有三種方式以下(默認是:每秒fsync一次)線程

appendonly yes              //啓用aof持久化方式
# appendfsync always      //每收到寫命令就當即強制寫入磁盤,最慢的,可是保證徹底的持久化,不推薦使用
appendfsync everysec     //每秒鐘強制寫入磁盤一次,在性能和持久化方面作了很好的折中,推薦
# appendfsync no         //徹底依賴os,性能最好,持久化沒保證(操做系統自身的同步)
no-appendfsync-on-rewrite  yes  //正在導出rdb快照的過程當中,要不要中止同步aof
auto-aof-rewrite-percentage 100  //aof文件大小比起上次重寫時的大小,增加率100%時,重寫
auto-aof-rewrite-min-size 64mb //aof文件,至少超過64M時,重寫

重寫:內存中有N多數據,是NNN次語句獲得的,爲了節省日誌文件空間,將內存數據轉化爲直接優化過的語句,不是之前的(詳細)操做步驟,可是達到的「數據」效果是同樣的。 aof 的方式也同時帶來了另外一個問題。持久化文件會變的愈來愈大。例如咱們調用incr test命令100次,文件中必須保存所有的100條命令,其實有99條都是多餘的。由於要恢復數據庫的狀態其實文件中保存一條set test 100就夠了。爲了壓縮aof的持久化文件。redis提供了 bgrewriteaof 命令。收到此命令redis將使用與快照相似的方式將內存中的數據 以命令的方式保存到臨時文件中,最後替換原來的文件。aof 過程:日誌

1.redis調用fork ,如今有父子兩個進程

2.子進程根據內存中的數據庫快照,往臨時文件中寫入重建數據庫狀態的命令
 
3.父進程繼續處理client請求,除了把寫命令寫入到原來的aof文件中。同時把收到的寫命令緩存起來。這樣就能保證若是子進程重寫失敗的話並不會出問題。

4.當子進程把快照內容寫入已命令方式寫到臨時文件中後,子進程發信號通知父進程。而後父進程把緩存的寫命令也寫入到臨時文件。

5.如今父進程可使用臨時文件替換老的aof文件,並重命名,後面收到的寫命令也開始往新的aof文件中追加。

須要注意到是重寫aof文件的操做,並無讀取舊的aof文件,而是將整個內存中的數據庫內容用命令的方式重寫了一個新的aof文件,這點和快照有點相似。

注意:

  • aof和rdb同時存在的時候,有限使用aof恢復數據;
  • aof和rdb恢復的時候,誰快,rdb快,直接拷貝數據,aof還要執行語句;
  • 建議同時使用aof 和 rdb
  • aof 文件 和 rdb文件 在下次redis啓動的時候會執行或載入,達到備份的目的。
相關文章
相關標籤/搜索