redis學習(九)——數據持久化

1、概述redis

      Redis的強大性能很大程度上都是由於全部數據都是存儲在內存中的,然而當Redis重啓後,全部存儲在內存中的數據將會丟失,在不少狀況下是沒法容忍這樣的事情的。因此,咱們須要將內存中的數據持久化!典型的須要持久化數據的場景以下:數據庫

  • 將Redis做爲數據庫使用;
  • 將Redis做爲緩存服務器使用,可是緩存miss後會對性能形成很大影響,全部緩存同時失效時會形成服務雪崩,沒法響應。

本文介紹Redis所支持的兩種數據持久化方式。windows

2、Redis數據持久化緩存

      Redis支持兩種數據持久化方式:RDB方式和AOF方式。前者會根據配置的規則定時將內存中的數據持久化到硬盤上,後者則是在每次執行寫命令以後將命令記錄下來。兩種持久化方式能夠單獨使用,可是一般會將二者結合使用。安全

一、RDB方式服務器

     RDB方式的持久化是經過快照的方式完成的。當符合某種規則時,會將內存中的數據全量生成一份副本存儲到硬盤上,這個過程稱做」快照」,Redis會在如下幾種狀況下對數據進行快照:app

  • 根據配置規則進行自動快照;
  • 用戶執行SAVE, BGSAVE命令;
  • 執行FLUSHALL命令;
  • 執行復制(replication)時。

執行快照的場景異步

(1)根據配置自動快照函數

      Redis容許用戶自定義快照條件,當知足條件時自動執行快照。缺省狀況下,Redis把數據快照存放在磁盤上的二進制文件中,文件名爲dump.rdb,此外,咱們也能夠經過配置文件來修改Redis服務器dump快照的頻率,在打開redis.windows.conf文件以後,咱們搜索save,能夠看到下面的配置信息:工具

注意最後三行,分別表示:

在900秒(15分鐘)以後,若是至少有1個key發生變化,則dump內存快照;

在300秒(5分鐘)以後,若是至少有10個key發生變化,則dump內存快照;

在60秒(1分鐘)以後,若是至少有10000個key發生變化,則dump內存快照。

     每一個快照條件獨佔一行,他們之間是或(||)關係,只要知足任何一個就進行快照。上面配置save後的第一個參數T是時間,單位是秒,第二個參數M是更改的鍵的個數,含義是:當時間T內被更改的鍵的個數大於M時,自動進行快照。好比save 900 1的含義是15分鐘內(900s)被更改的鍵的個數大於1時,自動進行快照操做。

(2)執行SAVE或BGSAVE命令

除了讓Redis自動進行快照外,當咱們須要重啓,遷移,備份Redis時,咱們也能夠手動執行SAVE或BGSAVE命令主動進行快照操做。

  • SAVE命令:當執行SAVE命令時,Redis同步進行快照操做,期間會阻塞全部來自客戶端的請求,因此放數據庫數據較多時,應該避免使用該命令;
  • BGSAVE命令: 從命令名字就能看出來,這個命令與SAVE命令的區別就在於該命令的快照操做是在後臺異步進行的,進行快照操做的同時還能處理來自客戶端的請求。執行BGSAVE命令後Redis會立刻返回OK表示開始進行快照操做,若是想知道快照操做是否已經完成,可使用LASTSAVE命令返回最近一次成功執行快照的時間,返回結果是一個Unix時間戳。

(3)執行FLUSHALL命令

     當執行FLUSHALL命令時,Redis會清除數據庫中的全部數據。須要注意的是:不論清空數據庫的過程是否觸發了自動快照的條件,只要自動快照條件不爲空,Redis就會執行一次快照操做,當沒有定義自動快照條件時,執行FLUSHALL命令不會進行快照操做。

(4)執行復制

當設置了主從模式時,Redis會在複製初始化時進行自動快照。

快照原理

      Redis默認會將快照文件存儲在Redis當前進程的工做目錄的dump.rdb文件中,能夠經過配置文件中的dir和dbfilename兩個參數分別指定快照文件的存儲路徑和文件名,默認的存儲路徑和文件名以下圖所示:

快照執行的過程以下:

(1)Redis使用fork函數複製一份當前進程(父進程)的副本(子進程);
(2)父進程繼續處理來自客戶端的請求,子進程開始將內存中的數據寫入硬盤中的臨時文件;
(3)當子進程寫完全部的數據後,用該臨時文件替換舊的RDB文件,至此,一次快照操做完成。

須要注意的是:

在執行fork的時候操做系統(類Unix操做系統)會使用寫時複製(copy-on-write)策略,即fork函數發生的一刻,父進程和子進程共享同一塊內存數據,當父進程須要修改其中的某片數據(如執行寫命令)時,操做系統會將該片數據複製一份以保證子進程不受影響,因此RDB文件存儲的是執行fork操做那一刻的內存數據。因此RDB方式理論上是會存在丟數據的狀況的(fork以後修改的的那些沒有寫進RDB文件)。

      經過上述的介紹能夠知道,快照進行時是不會修改RDB文件的,只有完成的時候纔會用臨時文件替換老的RDB文件,因此就保證任什麼時候候RDB文件的都是完整的。這使得咱們能夠經過定時備份RDB文件來實現Redis數據的備份。RDB文件是通過壓縮處理的二進制文件,因此佔用的空間會小於內存中數據的大小,更有利於傳輸。

      Redis啓動時會自動讀取RDB快照文件,將數據從硬盤載入到內存,根據數量的不一樣,這個過程持續的時間也不盡相同,一般來說,一個記錄1000萬個字符串類型鍵,大小爲1GB的快照文件載入到內存須要20-30秒的時間。

示例

下面演示RDB方式持久化,首先使用配置有以下快照規則:

save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir ./

啓動Redis服務:

而後經過客戶端設置一個鍵值:

如今強行kill Redis服務,執行shutdown命令:

如今到D:\Redis_x64_321\目錄看,目錄下出現了Redis的快照文件dump.rdb:

如今從新啓動Redis,而後再用客戶端鏈接,檢查以前設置的key是否還存在:

能夠發現,以前設置的key在Redis重啓以後又經過快照文件dump.rdb恢復了。

二、AOF方式

     在使用Redis存儲非臨時數據時,通常都須要打開AOF持久化來下降進程終止致使的數據丟失,AOF能夠將Redis執行的每一條寫命令追加到硬盤文件中,這一過程顯然會下降Redis的性能,可是大部分狀況下這個影響是能夠接受的,另外,使用較快的硬盤能提升AOF的性能。

開啓AOF

默認狀況下,Redis沒有開啓AOF(append only file)持久化功能,能夠經過在配置文件中做以下配置啓用:

開啓以後,Redis每執行一條寫命令就會將該命令寫入硬盤中的AOF文件。AOF文件保存路徑和RDB文件路徑是一致的,都是經過dir參數配置,默認文件名是:appendonly.aof,能夠經過配置appendonlyfilename參數修改,例如:

AOF持久化的實現

AOF以純文本的形式記錄了Redis執行的寫命令,例如在開啓AOF持久化的狀況下執行以下命令:

而後查看D:\Redis_x64_321\appendonly.aof文件:

文件中的內容正是Redis剛纔執行的命令的內容,內容的格式就先不展開敘述了。

AOF文件重寫

      AOF文件是可識別的純文本,它的內容就是一個個的Redis標準命令,
      AOF日誌也不是徹底按客戶端的請求來生成日誌的,好比命令 INCRBYFLOAT 在記AOF日誌時就被記成一條SET記錄,由於浮點數操做可能在不一樣的系統上會不一樣,因此爲了不同一份日誌在不一樣的系統上生成不一樣的數據集,因此這裏只將操做後的結果經過SET來記錄。

      每一條寫命令都生成一條日誌,AOF文件會很大。

     AOF重寫是從新生成一份AOF文件,新的AOF文件中一條記錄的操做只會有一次,而不像一份老文件那樣,可能記錄了對同一個值的屢次操做。其生成過程和RDB相似,也是fork一個進程,直接遍歷數據,寫入新的AOF臨時文件。在寫入新文件的過程當中,全部的寫操做日誌仍是會寫到原來老的AOF文件中,同時還會記錄在內存緩衝區中。當重完操做完成後,會將全部緩衝區中的日誌一次性寫入到臨時文件中。而後調用原子性的rename命令用新的 AOF文件取代老的AOF文件。

 命令:BGREWRITEAOF, 咱們應該常常調用這個命令來來重寫。

============================================================================= 

假設Redis執行了以下命令:

      若是這全部的命令都寫到AOF文件的話,將是一個比較蠢的行爲,由於前面兩個命令會被第三個命令覆蓋,因此AOF文件徹底不須要保存前面兩個命令,事實上Redis確實就是這麼作的。刪除AOF文件中無用的命令的過程稱爲"AOF重寫",AOF重寫能夠在配置文件中作相應的配置,當知足配置的條件時,自動進行AOF重寫操做。配置以下:

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

第一行的意思是,目前的AOF文件的大小超過上一次重寫時的AOF文件的百分之多少時再次進行重寫,若是以前沒有重寫過,則以啓動時AOF文件大小爲依據。
第二行的意思是,當AOF文件的大小大於64MB時才進行重寫,由於若是AOF文件原本就很小時,有幾個無效的命令也是無傷大雅的事情。
這兩個配置項一般一塊兒使用。

咱們還能夠手動執行BGREWRITEAOF命令主動讓Redis重寫AOF文件:

執行重寫命令以後查看如今的AOF文件:

能夠看到,文件中並無再記錄set k v1這樣的無效命令。

同步硬盤數據

     雖然每次執行更改數據庫的內容時,AOF都會記錄執行的命令,可是因爲操做系統自己的硬盤緩存的緣故,AOF文件的內容並無真正地寫入硬盤,在默認狀況下,操做系統會每隔30s將硬盤緩存中的數據同步到硬盤,可是爲了防止系統異常退出而致使丟數據的狀況發生,咱們還能夠在Redis的配置文件中配置這個同步的頻率:

1 # appendfsync always
2 appendfsync everysec
3 # appendfsync no

第一行表示每次AOF寫入一個命令都會執行同步操做,這是最安全也是最慢的方式;
第二行表示每秒鐘進行一次同步操做,通常來講使用這種方式已經足夠;
第三行表示不主動進行同步操做,這是最不安全的方式。

選項:

  一、appendfsync no

  當設置appendfsync爲no的時候,Redis不會主動調用fsync去將AOF日誌內容同步到磁盤,因此這一切就徹底依賴於操做系統的調試了。對大多數Linux操做系統,是每30秒進行一次fsync,將緩衝區中的數據寫到磁盤上。

  二、appendfsync everysec

      當設置appendfsync爲everysec的時候,Redis會默認每隔一秒進行一次fsync調用,將緩衝區中的數據寫到磁盤。可是當這一次的fsync調用時長超過1秒時。Redis會採起延遲fsync的策略,再等一秒鐘。也就是在兩秒後再進行fsync,這一次的fsync就無論會執行多長時間都會進行。這時候因爲在fsync時文件描述符會被阻塞,因此當前的寫操做就會阻塞。因此,結論就是:在絕大多數狀況下,Redis會每隔一秒進行一次fsync。在最壞的狀況下,兩秒鐘會進行一次fsync操做。這一操做在大多數數據庫系統中被稱爲group commit,就是組合屢次寫操做的數據,一次性將日誌寫到磁盤。

  三、appednfsync always

      當設置appendfsync爲always時,每一次寫操做都會調用一次fsync,這時數據是最安全的,固然,因爲每次都會執行fsync,因此其性能也會受到影響。

   建議採用 appendfsync everysec(缺省方式)

  快照模式能夠和AOF模式同時開啓,互補影響。

3、兩者的區別

     RDB持久化是指在指定的時間間隔內將內存中的數據集快照寫入磁盤,實際操做過程是fork一個子進程,先將數據集寫入臨時文件,寫入成功後,再替換以前的文件,用二進制壓縮存儲。

 AOF持久化以日誌的形式記錄服務器所處理的每個寫、刪除操做,查詢操做不會記錄,以文本的方式記錄,能夠打開文件看到詳細的操做記錄。

4、兩者優缺點

RDB存在哪些優點呢?

    1). 一旦採用該方式,那麼你的整個Redis數據庫將只包含一個文件,這對於文件備份而言是很是完美的。好比,你可能打算每一個小時歸檔一次最近24小時的數據,同時還要天天歸檔一次最近30天的數據。經過這樣的備份策略,一旦系統出現災難性故障,咱們能夠很是容易的進行恢復。
    2). 對於災難恢復而言,RDB是很是不錯的選擇。由於咱們能夠很是輕鬆的將一個單獨的文件壓縮後再轉移到其它存儲介質上。
    3). 性能最大化。對於Redis的服務進程而言,在開始持久化時,它惟一須要作的只是fork出子進程,以後再由子進程完成這些持久化的工做,這樣就能夠極大的避免服務進程執行IO操做了。
    4). 相比於AOF機制,若是數據集很大,RDB的啓動效率會更高。
    
RDB又存在哪些劣勢呢?

    1). 若是你想保證數據的高可用性,即最大限度的避免數據丟失,那麼RDB將不是一個很好的選擇。由於系統一旦在定時持久化以前出現宕機現象,此前沒有來得及寫入磁盤的數據都將丟失。
    2). 因爲RDB是經過fork子進程來協助完成數據持久化工做的,所以,若是當數據集較大時,可能會致使整個服務器中止服務幾百毫秒,甚至是1秒鐘。

AOF的優點有哪些呢? 

  1). 該機制能夠帶來更高的數據安全性,即數據持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不一樣步。事實上,每秒同步也是異步完成的,其效率也是很是高的,所差的是一旦系統出現宕機現象,那麼這一秒鐘以內修改的數據將會丟失。而每修改同步,咱們能夠將其視爲同步持久化,即每次發生的數據變化都會被當即記錄到磁盤中。能夠預見,這種方式在效率上是最低的。至於無同步,無需多言,我想你們都能正確的理解它。
    2). 因爲該機制對日誌文件的寫入操做採用的是append模式,所以在寫入過程當中即便出現宕機現象,也不會破壞日誌文件中已經存在的內容。然而若是咱們本次操做只是寫入了一半數據就出現了系統崩潰問題,不用擔憂,在Redis下一次啓動以前,咱們能夠經過redis-check-aof工具來幫助咱們解決數據一致性的問題。
    3). 若是日誌過大,Redis能夠自動啓用rewrite機制。即Redis以append模式不斷的將修改數據寫入到老的磁盤文件中,同時Redis還會建立一個新的文件用於記錄此期間有哪些修改命令被執行。所以在進行rewrite切換時能夠更好的保證數據安全性。
    4). AOF包含一個格式清晰、易於理解的日誌文件用於記錄全部的修改操做。事實上,咱們也能夠經過該文件完成數據的重建。
    
AOF的劣勢有哪些呢?
    1). 對於相同數量的數據集而言,AOF文件一般要大於RDB文件。RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。
    2). 根據同步策略的不一樣,AOF在運行效率上每每會慢於RDB。總之,每秒同步策略的效率是比較高的,同步禁用策略的效率和RDB同樣高效。

   兩者選擇的標準,就是看系統是願意犧牲一些性能,換取更高的緩存一致性(aof),仍是願意寫操做頻繁的時候,不啓用備份來換取更高的性能,待手動運行save的時候,再作備份(rdb)。rdb這個就更有些 eventually consistent的意思了。

5、經常使用配置

RDB持久化配置

Redis會將數據集的快照dump到dump.rdb文件中。此外,咱們也能夠經過配置文件來修改Redis服務器dump快照的頻率,在打開6379.conf文件以後,咱們搜索save,能夠看到下面的配置信息:
    save 900 1              #在900秒(15分鐘)以後,若是至少有1個key發生變化,則dump內存快照。
    save 300 10            #在300秒(5分鐘)以後,若是至少有10個key發生變化,則dump內存快照。
    save 60 10000        #在60秒(1分鐘)以後,若是至少有10000個key發生變化,則dump內存快照。

AOF持久化配置 

在Redis的配置文件中存在三種同步方式,它們分別是:    appendfsync always     #每次有數據修改發生時都會寫入AOF文件。    appendfsync everysec  #每秒鐘同步一次,該策略爲AOF的缺省策略。    appendfsync no          #從不一樣步。高效可是數據不會被持久化。

相關文章
相關標籤/搜索