Redis研究(十一)—資料持久化,redis研究資料

來源:互聯網
上載者:User

Redis研究(十一)—資料持久化,redis研究資料
       Redis的強勁效能很大程度上是由於其將所有資料都儲存在了記憶體中,為了使Redis在重啟之後仍能保證資料不丟失,需要將資料從記憶體中以某種形式同步到硬碟中,這一過程就是持久化。

       Redis支援兩種方式的持久化,一種是RDB方式,一種是AOF方式。可以單獨使用其中一種或將二者結合使用。


1. RDB方式

       RDB方式的持久化是通過快照(snapshotting )完成的,當符合一定條件時Redis會自動將記憶體中的所有資料進行快照並儲存在硬碟上。進行快照的條件可以由使用者在設定檔中自訂,由兩個參數構成:時間和改動的鍵的個數。當在指定的時間內被更改的鍵的個數大於指定的數值時就會進行快照。RDB是Redis預設採用的持久化方式,在設定檔中已經預置了3個條件:

save  900 1save  300 10save  60 10000

save參數指定了快照條件,可以存在多個條件,條件之間是“或”的關係。如上所說,save 900 1的意思是在15分鐘(900秒鐘)內有至少一個鍵被更改則進行快照。

如果想要禁用自動快照,只需要將所有的save參數刪除即可。

Redis預設會將快照檔案儲存體在目前的目錄的dump.rdb檔案中,可以通過配置dir和dbfilename兩個參數分別指定快照檔案的儲存路徑和檔案名稱。


理清Redis實現快照的過程對我們瞭解快照檔案的特性有很大的協助。快照的過程如下。
(1)Redis使用fork 函數複製一份當前進程(父進程)的副本(子進程);
(2)父進程繼續接收並處理用戶端發來的命令,而子進程開始將記憶體中的資料寫入硬碟中的臨時檔案;
(3)當子進程寫入完所有資料後會用該臨時檔案替換舊的RDB檔案,至此一次快照操作完成。


     在執行fork 的時候作業系統(類Unix 作業系統)會使用寫時複製(copy-on-write)策略,即fork 函數發生的一刻父子進程共用同一記憶體資料,當父進程要更改其中某片資料時(如執行一個寫命令),作業系統會將該片資料複製一份以保證子進程的資料不受影響,所以新的RDB檔案儲存體的是執行fork 一刻的記憶體資料。


     通過上述過程可以發現Redis在進行快照的過程中不會修改RDB檔案,只有快照結束後才會將舊的檔案替換成新的,也就是說任何時候RDB檔案都是完整的。這使得我們可以通過定時備份RDB檔案來實現RedisDatabase Backup。RDB檔案是經過壓縮(可以配置rdbcompression 參數以禁用壓縮節省CPU佔用)的二進位格式,所以佔用的空間會小於記憶體中的資料大小,更加利於傳輸。


     除了自動快照,還可以手動發送SAVE或BGSAVE命令讓Redis執行快照,兩個命令的區別在於,前者是由主進程進行快照操作,會阻塞住其他請求,後者會通過fork 子進程進行快照操作。

    

     Redis啟動後會讀取RDB快照檔案,將資料從硬碟載入到記憶體。根據資料量大小與結構和伺服器效能不同,這個時間也不同。

通常將一個記錄一千萬個字串類型鍵、大小為1GB的快照檔案載入到記憶體中需要花費20~30秒鐘。


     通過RDB方式實現持久化,一旦Redis異常退出,就會丟失最後一次快照以後更改的所有資料。這就需要開發人員根據具體的應用場合,通過組合設定自動快照條件的方式來將可能發生的資料損失控制在能夠接受的範圍。如果資料很重要以至於無法承受任何損失,則可以考慮使用AOF方式進行持久化。


2. AOF 方式

      預設情況下Redis沒有開啟AOF(append only  file)方式的持久化,可以通過appendonly 參數開啟:

appendonly yes

     開啟AOF持久化後每執行一條會更改Redis中的資料的命令,Redis就會將該命令寫入硬碟中的AOF檔案。AOF檔案的儲存位置和RDB檔案的位置相同,都是通過dir參數設定的,預設的檔案名稱是appendonly.aof ,可以通過appendfilename參數修改:
append file name  appendonly.aof

下面講解AOF持久化的具體實現,假設在開啟AOF持久化的情況下執行了如下4個命令:
SET foo 1SET foo 2SET foo 3GET foo

Redis會將前3條命令寫入AOF檔案中,此時AOF檔案中的內容如下:
*2$6SELECT$10*3$3set$3foo$11*3$3set$3foo$12*3$3set$3foo$13

     可見AOF檔案是純文字檔案,其內容正是Redis用戶端向Redis發送的原始通訊協定的內容(為了便於閱讀,這裡將實際的命令部分以粗體顯示),從中可見Redi s確實只記錄了前3條命令。然而這時有一個問題是前2條命令其實都是冗餘的,因為這兩條的執行結果會被第三條命令覆蓋。隨著執行的命令越來越多,AOF檔案的大小也會越來越大,即使記憶體中實際的資料可能並沒有多少。很自然地,我們希望Redi s可以自動最佳化AOF檔案,就上例而言,就是將前兩條無用的記錄刪除,只保留第三條。實際上Redis也正是這樣做的,每當達到一定條件時Redis就會自動重寫AOF檔案,這個條件可以在設定檔中設定:
auto-aof-rewrite-percentage 100auto-aof-rewrite-min-size  64mb

auto-aof-rewrite-percentage參數的意義是當目前的AOF檔案大小超過上一次重寫時的AOF檔案大小的百分之多少時會再次進行重寫,如果之前沒有重寫過,則以啟動時的AOF檔案大小為依據。

auto-aof-rewrite-min-size參數限制了允許重寫的最小AOF檔案大小,通常在AOF檔案很小的情況下即使其中有很多冗餘的命令我們也並不太關心。

除了讓Redis自動執行重寫外,我們還可以主動使用BGREWRI TEAOF命令手動執行AOF重寫。

上例中的AOF檔案重寫後的內容為:
*2$6SELECT$10*3$3SET$3foo$13

     可見冗餘的命令已經被刪除了。重寫的過程只和記憶體中的資料有關,和之前的AOF檔案無關,這與RDB很相似,只不過二者的檔案格式完全不同。


     在啟動時Redis會逐個執行AOF檔案中的命令來將硬碟中的資料載入到記憶體中,載入的速度相較RDB會慢一些。


     需要注意的是雖然每次執行更改資料庫內容的操作時,AOF都會將命令記錄在AOF檔案中,但是事實上,由於作業系統的緩衝機制,資料並沒有真正地寫入硬碟,而是進入了系統的硬碟緩衝。在預設情況下系統每30秒會執行一次同步操作,以便將硬碟緩衝中的內容真正地寫入硬碟,在這30秒的過程中如果系統異常退出則會導致硬碟緩衝中的資料丟失。一般來講啟用AOF持久化的應用都無法容忍這樣的損失,這就需要Redis在寫入AOF檔案後主動要求系統將緩衝內容同步到硬碟中。


    在Redis中我們可以通過appendfsync參數設定同步的時機:

# appendfsync alwaysappendfsync everysec# appendfsync no

      預設情況下Redis採用everysec 規則,即每秒執行一次同步操作。always表示每次執行寫入都會執行同步,這是最安全也是最慢的方式。no表示不主動進行同步操作,而是完全交由作業系統來做(即每30秒一次),這是最快但最不安全的方式。一般情況下使用預設值everysec就足夠了,既兼顧了效能又保證了安全。


     Redis允許同時開啟AOF和RDB,既保證了資料安全(AOF)又使得進行備份(RDB)等操作十分容易。此時重新啟動Redis後Redis會使用AOF檔案來恢複資料,因為AOF方式的持久化可能丟失的資料更少。

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.