redis的持久化方式:RDB和AOF




   數據持久化通俗講就是把數據保存到磁盤上,保證不會由於斷電等因素丟失數據。redis

   

       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(異步)作快照。app


    下面是默認的快照保存配置運維

save 900 1  #900秒內若是超過1個key被修改,則發起快照保存
save 300 10 #300秒內容如超過10個key被修改,則發起快照保存
save 60 10000
異步


工做原理:ide

1.當redis須要作持久化時,redis會fork一個子進程memcached


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


3.當子進程完成寫臨時文件後,將原來的RDB替換掉,這樣的好處就是能夠copy-on-writeCopy-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數。

相關文章
相關標籤/搜索