redis的持久化方式

很是感謝《redis實戰》真本書,本文大多內容也參考了書中的內容。很是推薦你們看一下《redis實戰》這本書,感受書中的不少理論性東西仍是很不錯的。html

爲何本文的名字要加上春夏秋冬又一春,哈哈 ,這是一部韓國的電影,我感受電影不錯,因此就用在文章名字上了,沒有什麼特別的含義,而後下面的有些配圖也是電影相關鏡頭。git

春夏秋冬又一春

不少時候咱們須要持久化數據也就是將內存中的數據寫入到硬盤裏面,大部分緣由是爲了以後重用數據(好比重啓機器、機器故障以後回覆數據),或者是爲了防止系統故障而將數據備份到一個遠程位置。github

Redis不一樣於Memcached的很重一點就是,Redis支持持久化,並且支持兩種不一樣的持久化操做。Redis的一種持久化方式叫快照(snapshotting,RDB),另外一種方式是只追加文件(append-only file,AOF).這兩種方法各有千秋,下面我會詳細這兩種持久化方法是什麼,怎麼用,如何選擇適合本身的持久化方法。redis

快照(snapshotting)持久化

Redis能夠經過建立快照來得到存儲在內存裏面的數據在某個時間點上的副本。Redis建立快照以後,能夠對快照進行備份,能夠將快照複製到其餘服務器從而建立具備相同數據的服務器副本(Redis主從結構,主要用來提升Redis性能),還能夠將快照留在原地以便重啓服務器的時候使用。安全

春夏秋冬又一春

快照持久化是Redis默認採用的持久化方式,在redis.conf配置文件中默認有此下配置:服務器

save 900 1              #在900秒(15分鐘)以後,若是至少有1個key發生變化,Redis就會自動觸發BGSAVE命令建立快照。

save 300 10            #在300秒(5分鐘)以後,若是至少有10個key發生變化,Redis就會自動觸發BGSAVE命令建立快照。

save 60 10000        #在60秒(1分鐘)以後,若是至少有10000個key發生變化,Redis就會自動觸發BGSAVE命令建立快照。

根據配置,快照將被寫入dbfilename選項指定的文件裏面,並存儲在dir選項指定的路徑上面。若是在新的快照文件建立完畢以前,Redis、系統或者硬件這三者中的任意一個崩潰了,那麼Redis將丟失最近一次建立快照寫入的全部數據。markdown

舉個例子:假設Redis的上一個快照是2:35開始建立的,而且已經建立成功。下午3:06時,Redis又開始建立新的快照,而且在下午3:08快照建立完畢以前,有35個鍵進行了更新。若是在下午3:06到3:08期間,系統發生了崩潰,致使Redis沒法完成新快照的建立工做,那麼Redis將丟失下午2:35以後寫入的全部數據。另外一方面,若是系統剛好在新的快照文件建立完畢以後崩潰,那麼Redis將丟失35個鍵的更新數據。app

建立快照的辦法有以下幾種:svg

  • BGSAVE命令: 客戶端向Redis發送 BGSAVE命令 來建立一個快照。對於支持BGSAVE命令的平臺來講(基本上全部平臺支持,除了Windows平臺),Redis會調用fork來建立一個子進程,而後子進程負責將快照寫入硬盤,而父進程則繼續處理命令請求。
  • SAVE命令: 客戶端還能夠向Redis發送 SAVE命令 來建立一個快照,接到SAVE命令的Redis服務器在快照建立完畢以前不會再響應任何其餘命令。SAVE命令不經常使用,咱們一般只會在沒有足夠內存去執行BGSAVE命令的狀況下,又或者即便等待持久化操做執行完畢也無所謂的狀況下,纔會使用這個命令。
  • save選項: 若是用戶設置了save選項(通常會默認設置),好比 save 60 10000,那麼從Redis最近一次建立快照以後開始算起,當「60秒以內有10000次寫入」這個條件被知足時,Redis就會自動觸發BGSAVE命令。
  • SHUTDOWN命令: 當Redis經過SHUTDOWN命令接收到關閉服務器的請求時,或者接收到標準TERM信號時,會執行一個SAVE命令,阻塞全部客戶端,再也不執行客戶端發送的任何命令,並在SAVE命令執行完畢以後關閉服務器。
  • 一個Redis服務器鏈接到另外一個Redis服務器: 當一個Redis服務器鏈接到另外一個Redis服務器,並向對方發送SYNC命令來開始一次複製操做的時候,若是主服務器目前沒有執行BGSAVE操做,或者主服務器並不是剛剛執行完BGSAVE操做,那麼主服務器就會執行BGSAVE命令

若是系統真的發生崩潰,用戶將丟失最近一次生成快照以後更改的全部數據。所以,快照持久化只適用於即便丟失一部分數據也不會形成一些大問題的應用程序。不能接受這個缺點的話,能夠考慮AOF持久化。性能

AOF(append-only file)持久化

與快照持久化相比,AOF持久化 的實時性更好,所以已成爲主流的持久化方案。默認狀況下Redis沒有開啓AOF(append only file)方式的持久化,能夠經過appendonly參數開啓:

appendonly yes

開啓AOF持久化後每執行一條會更改Redis中的數據的命令,Redis就會將該命令寫入硬盤中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是經過dir參數設置的,默認的文件名是appendonly.aof。

春夏秋冬又一春

在Redis的配置文件中存在三種同步方式,它們分別是:

appendfsync always     #每次有數據修改發生時都會寫入AOF文件,這樣會嚴重下降Redis的速度
appendfsync everysec  #每秒鐘同步一次,顯示地將多個寫命令同步到硬盤
appendfsync no      #讓操做系統決定什麼時候進行同步

appendfsync always 能夠實現將數據丟失減到最少,不過這種方式須要對硬盤進行大量的寫入並且每次只寫入一個命令,十分影響Redis的速度。另外使用固態硬盤的用戶謹慎使用appendfsync always選項,由於這會明顯下降固態硬盤的使用壽命。

爲了兼顧數據和寫入性能,用戶能夠考慮 appendfsync everysec選項 ,讓Redis每秒同步一次AOF文件,Redis性能幾乎沒受到任何影響。並且這樣即便出現系統崩潰,用戶最多隻會丟失一秒以內產生的數據。當硬盤忙於執行寫入操做的時候,Redis還會優雅的放慢本身的速度以便適應硬盤的最大寫入速度。

appendfsync no 選項通常不推薦,這種方案會使Redis丟失不定量的數據並且若是用戶的硬盤處理寫入操做的速度不夠的話,那麼當緩衝區被等待寫入的數據填滿時,Redis的寫入操做將被阻塞,這會致使Redis的請求速度變慢。

雖然AOF持久化很是靈活地提供了多種不一樣的選項來知足不一樣應用程序對數據安全的不一樣要求,但AOF持久化也有缺陷——AOF文件的體積太大。

重寫/壓縮AOF

AOF雖然在某個角度能夠將數據丟失下降到最小並且對性能影響也很小,可是極端的狀況下,體積不斷增大的AOF文件極可能會用完硬盤空間。另外,若是AOF體積過大,那麼還原操做執行時間就可能會很是長。

爲了解決AOF體積過大的問題,用戶能夠向Redis發送 BGREWRITEAOF命令 ,這個命令會經過移除AOF文件中的冗餘命令來重寫(rewrite)AOF文件來減少AOF文件的體積。BGREWRITEAOF命令和BGSAVE建立快照原理十分類似,因此AOF文件重寫也須要用到子進程,這樣會致使性能問題和內存佔用問題,和快照持久化同樣。更糟糕的是,若是不加以控制的話,AOF文件的體積可能會比快照文件大好幾倍。

文件重寫流程:

文件重寫流程 和快照持久化能夠經過設置save選項來自動執行BGSAVE同樣,AOF持久化也能夠經過設置

auto-aof-rewrite-percentage

選項和

auto-aof-rewrite-min-size

選項自動執行BGREWRITEAOF命令。舉例:假設用戶對Redis設置了以下配置選項而且啓用了AOF持久化。那麼當AOF文件體積大於64mb,而且AOF的體積比上一次重寫以後的體積大了至少一倍(100%)的時候,Redis將執行BGREWRITEAOF命令。

auto-aof-rewrite-percentage 100  
auto-aof-rewrite-min-size 64mb

不管是AOF持久化仍是快照持久化,將數據持久化到硬盤上都是很是有必要的,但除了進行持久化外,用戶還必須對持久化獲得的文件進行備份(最好是備份到不一樣的地方),這樣才能儘可能避免數據丟失事故發生。若是條件容許的話,最好能將快照文件和從新重寫的AOF文件備份到不一樣的服務器上面。

隨着負載量的上升,或者數據的完整性變得 愈來愈重要時,用戶可能須要使用到複製特性。

Redis 4.0 對於持久化機制的優化

Redis 4.0 開始支持 RDB 和 AOF 的混合持久化(默認關閉,能夠經過配置項 aof-use-rdb-preamble 開啓)。

若是把混合持久化打開,AOF 重寫的時候就直接把 RDB 的內容寫到 AOF 文件開頭。這樣作的好處是能夠結合 RDB 和 AOF 的優勢, 快速加載同時避免丟失過多的數據。固然缺點也是有的, AOF 裏面的 RDB 部分就是壓縮格式再也不是 AOF 格式,可讀性較差。

參考:

《Redis實戰》

深刻學習Redis(2):持久化

相關文章
相關標籤/搜索