天天看點

redis的持久化方式:RDB和AOF

   資料持久化通俗講就是把資料儲存到磁盤上,保證不會因為斷電等因素丢失資料。

       Redis是一種進階key-value資料庫。它跟memcached類似,不過資料可以持久化,而且支援的資料類型很豐富。有字元串,連結清單,集 合和有序集合。支援在伺服器端計算集合的并,交和補集(difference)等,還支援多種排序功能。是以Redis也可以被看成是一個資料結構服務 器。

      Redis的所有資料都是儲存在記憶體中,然後不定期的通過異步方式儲存到磁盤上(這稱為“半持久化模式”);也可以把每一次資料變化都寫入到一個append only file(aof)裡面(這稱為“全持久化模式”)。

      redis支援兩種持久化方式,一種是 Snapshotting(快照)也是預設方式,另一種是Append-only file(縮寫aof)的方式。

1.Snapshotting(RDB)

    預設redis是會以快照的形式将資料持久化到磁盤的(一個二進 制檔案,dump.rdb,這個檔案名字可以指定),在配置檔案中的格式是:save N M表示在N秒之内,redis至少發生M次修改則redis抓快照到磁盤。當然我們也可以手動執行save或者bgsave(異步)做快照。

    下面是預設的快照儲存配置

save 900 1  #900秒内如果超過1個key被修改,則發起快照儲存

save 300 10 #300秒内容如超過10個key被修改,則發起快照儲存

save 60 10000

工作原理:

1.當redis需要做持久化時,redis會fork一個子程序。

2. 父程序繼續處理client請求,子程序負責将記憶體内容寫入到臨時RDB檔案。由于os的寫時複制機制(copy on write)父子程序會共享相同的實體頁面,當父程序處理寫請求時os會為父程序要修改的頁面建立副本,而不是寫共享的頁面。是以子程序的位址空間(位址空間(address space)表示任何一個計算機實體所占用的記憶體大小)内的數 據是fork時刻整個資料庫的一個快照。

3.當子程序完成寫臨時檔案後,将原來的RDB替換掉,這樣的好處就是可以copy-on-write(Copy-on-write 寫時複制      在對資料進行修改的時候,不會直接在原來的資料位置上進行操作,而是重新找個位置修改,這樣的好處是一旦系統突然斷電,重新開機之後不需要做Fsck.)

      client 也可以使用save或者bgsave指令通知redis做一次快照持久化。

      save操作是在主線程中儲存快照的,由于redis是用一個主線程來處理所有 client的請求,這種方式會阻塞所有client請求。是以不推薦使用。

      另一點需要注意的是,每次快照持久化都是将記憶體資料完整寫入到磁盤一次,并不 是增量的隻同步髒資料。如果資料量大的話,而且寫操作比較多,必然會引起大量的磁盤io操作,可能會嚴重影響性能。

     另外由于快照方式是在一定間隔時間做一次的,是以如果redis意外down掉的話,就會丢失最後一次快照後的所有修改。如果應用要求不能丢失任何修改的話,可以采用aof持久化方式。

2.Append-only file(AOF)

     AOF定義:以日志的形式記錄每個操作,将Redis執行過的所有指令全部記錄下來(讀操作不記錄),隻許追加檔案但不可以修改檔案,Redis啟動時會讀取AOF配置檔案重構資料。

換句話說,就是Redis重新開機就會根據日志内容從頭到尾執行一次來完成資料的恢複工作。

      AOF比快照方式有更好的持久化性,是由于在使用AOF持久化方式時,redis會将每一個收到的寫指令都通過write函數追加到檔案中(預設是 appendonly.aof)。

     當redis重新開機時會通過重新執行檔案中儲存的寫指令來在記憶體中重建整個資料庫的内容。當然由于os會在核心中緩存 write做的修改,是以可能不是立即寫到磁盤上。這樣aof方式的持久化也還是有可能會丢失部分修改。

    不過我們可以通過配置檔案告訴redis我們想要 通過fsync函數強制os寫入到磁盤的時機。

 有三種方式如下(預設是:每秒fsync一次)

appendonly yes              //啟用aof持久化方式

# appendfsync always      //每次收到寫指令就立即強制寫入磁盤,最慢的,但是保證完全的持久化,不推薦使用

appendfsync everysec     //每秒鐘強制寫入磁盤一次,在性能和持久化方面做了很好的折中,推薦

# appendfsync no    //完全依賴os,性能最好,持久化沒保證

Tip:

  一.RDB與AOF同時開啟  預設先加載AOF的配置檔案

  二.相同資料集,AOF檔案要遠大于RDB檔案,恢複速度慢于RDB

  三.AOF運作效率慢于RDB,但是同步政策效率好,不同步效率和RDB相同

1.表示是否開啟AOF持久化:

  appendonly yes(預設no,關閉) 

2.AOF持久化配置檔案的名稱:

  appendfilename "appendonly.aof"

3.AOF持久化政策(預設每秒):

  appendfsync always (同步持久化,每次發生資料變更會被立即記錄到磁盤,性能差但資料完整性比較好)

  appendfsync everysec (異步操作,每秒記錄,如果一秒鐘内當機,有資料丢失)

  appendfsync no  (不同步)

4.AOF配置檔案損壞修複方法:

  進入redis安裝路徑 執行 redis-check-aof --fix AOF配置檔案名稱

5.AOF的Rewrite(重寫) :

  定義:AOF采用檔案追加的方式持久化資料,是以檔案會越來越大,為了避免這種情況發生,增加了重寫機制

當AOF檔案的大小超過了配置所設定的阙值時,Redis就會啟動AOF檔案壓縮,隻保留可以恢複資料的最小指令集,可以使用指令bgrewriteaof

原理:當AOF增長過大時,會fork出一條新的程序将檔案重寫(也是先寫臨時檔案最後rename),周遊新程序的記憶體資料,每條記錄有一條set語句。

重寫AOF檔案并沒有操作舊的AOF檔案,而是将整個記憶體中的資料内容用指令的方式重寫了一個新的aof檔案(有點類似快照)

觸發機制:Redis會記錄上次重寫時的AOF檔案大小,預設配置時當AOF檔案大小是上次rewrite後大小的一倍且檔案大于64M時觸發

  auto-aof-rewrite-percentage 100  (一倍)

   auto-aof-rewrite-min-size 64mb

6.RDB與AOF的選擇:

做備份:當資料量大,且對恢複速度有要求,并且資料的一緻性要求不高的話,可以隻使用RDB

隻做緩存:不用開啟任何的持久化方式

兩者都開啟的建議:RDB資料不實時,同時使用兩者時伺服器隻會找AOF檔案,可不可以隻使用AOF?作者建議不要,因為RDB更适合備份資料庫(AOF在不斷變化,不好備份)

快速重新開機,而且不會又AOF可能潛在的BUG,留作萬一的手段。

其實快照和aof一樣,都使用了Copy-on-write技術。多次試驗發現每次做資料dump的時候,記憶體都會擴大一倍,這個時候會有三種情況:

一:實體記憶體足以滿足,這個時候dump非常快,性能最好

二:實體記憶體+虛拟記憶體可以滿足,這個時候dump速度會比較慢,磁盤swap繁忙,服務性能也會下降。所幸的是經過一段比較長的時候資料dump完成了,然後記憶體恢複正常。這個情況系統穩定性差。

三: 實體記憶體+虛拟記憶體不能滿足,這個時候dump一直死着,時間久了機器挂掉。這個情況就是災難!

如果資料要做持久化又想保證穩定性,建議留白一半的實體記憶體。如果覺得無法接受還是有辦法,下面講:

     快照和aof雖然都使用Copy-on-write,但有個不同點,快照你無法預測redis什麼時候做dump,aof可以通過bgrewriteaof指令控制dump的時機。

根據這點我可以在一個伺服器上開啟多個redis節點(利用多CPU),使用aof的持久化方式。

      例 如在24G記憶體的伺服器上開啟3個節點,每天用bgrewriteaof定期重新整理資料,每個節點dump的時間都不一樣,這 樣理論上每個節點可以消耗6G記憶體,一共使用18G記憶體,另外6G記憶體在單個節點dump時用到,記憶體一下多利用了6G! 當然節點開的越多記憶體的使用率也越高。如果帶寬不是問題,節點數建議 = CPU數。

本文轉自寫個部落格騙錢部落格51CTO部落格,原文連結http://blog.51cto.com/dadonggg/1955928如需轉載請自行聯系原作者

菜鳥東哥