天天看點

Redis詳解(六)------ RDB 持久化

   前面我們說過,Redis 相對于 Memcache 等其他的緩存産品,有一個比較明顯的優勢就是 Redis 不僅僅支援簡單的key-value類型的資料,同時還提供list,set,zset,hash等資料結構的存儲。這幾種豐富的資料類型我們花了兩篇文章進行了詳細的介紹,接下來我們要介紹 Redis 的另外一大優勢——持久化。

  由于 Redis 是一個記憶體資料庫,所謂記憶體資料庫,就是将資料庫中的内容儲存在記憶體中,這與傳統的MySQL,Oracle等關系型資料庫直接将内容儲存到硬碟中相比,記憶體資料庫的讀寫效率比傳統資料庫要快的多(記憶體的讀寫效率遠遠大于硬碟的讀寫效率)。但是儲存在記憶體中也随之帶來了一個缺點,一旦斷電或者當機,那麼記憶體資料庫中的資料将會全部丢失。

  為了解決這個缺點,Redis提供了将記憶體資料持久化到硬碟,以及用持久化檔案來恢複資料庫資料的功能。Redis 支援兩種形式的持久化,一種是RDB快照(snapshotting),另外一種是AOF(append-only-file)。本篇部落格先對 RDB 快照進行介紹。

1、RDB 簡介

  RDB是Redis用來進行持久化的一種方式,是把目前記憶體中的資料集快照寫入磁盤,也就是 Snapshot 快照(資料庫中所有鍵值對資料)。恢複時是将快照檔案直接讀到記憶體裡。

2、觸發方式

  RDB 有兩種觸發方式,分别是自動觸發和手動觸發。

①、自動觸發

  在 redis.conf 配置檔案中的 SNAPSHOTTING 下,在

這篇文章

中我們介紹過。

  

Redis詳解(六)------ RDB 持久化

  ①、save:這裡是用來配置觸發 Redis的 RDB 持久化條件,也就是什麼時候将記憶體中的資料儲存到硬碟。比如“save m n”。表示m秒内資料集存在n次修改時,自動觸發bgsave(這個指令下面會介紹,手動觸發RDB持久化的指令)

  預設如下配置:

save 900 1:表示900 秒内如果至少有 1 個 key 的值變化,則儲存
save 300 10:表示300 秒内如果至少有 10 個 key 的值變化,則儲存
save 60 10000:表示60 秒内如果至少有 10000 個 key 的值變化,則儲存      

    當然如果你隻是用Redis的緩存功能,不需要持久化,那麼你可以注釋掉所有的 save 行來停用儲存功能。可以直接一個空字元串來實作停用:save ""

  ②、stop-writes-on-bgsave-error :預設值為yes。當啟用了RDB且最後一次背景儲存資料失敗,Redis是否停止接收資料。這會讓使用者意識到資料沒有正确持久化到磁盤上,否則沒有人會注意到災難(disaster)發生了。如果Redis重新開機了,那麼又可以重新開始接收資料了

  ③、rdbcompression ;預設值是yes。對于存儲到磁盤中的快照,可以設定是否進行壓縮存儲。如果是的話,redis會采用LZF算法進行壓縮。如果你不想消耗CPU來進行壓縮的話,可以設定為關閉此功能,但是存儲在磁盤上的快照會比較大。

  ④、rdbchecksum :預設值是yes。在存儲快照後,我們還可以讓redis使用CRC64算法來進行資料校驗,但是這樣做會增加大約10%的性能消耗,如果希望擷取到最大的性能提升,可以關閉此功能。

  ⑤、dbfilename :設定快照的檔案名,預設是 dump.rdb

  ⑥、dir:設定快照檔案的存放路徑,這個配置項一定是個目錄,而不能是檔案名。預設是和目前配置檔案儲存在同一目錄。

  也就是說通過在配置檔案中配置的 save 方式,當實際操作滿足該配置形式時就會進行 RDB 持久化,将目前的記憶體快照儲存在 dir 配置的目錄中,檔案名由配置的 dbfilename 決定。

②、手動觸發

  手動觸發Redis進行RDB持久化的指令有兩種:

  1、save

  該指令會阻塞目前Redis伺服器,執行save指令期間,Redis不能處理其他指令,直到RDB過程完成為止。

  顯然該指令對于記憶體比較大的執行個體會造成長時間阻塞,這是緻命的缺陷,為了解決此問題,Redis提供了第二種方式。

  2、bgsave

  執行該指令時,Redis會在背景異步進行快照操作,快照同時還可以響應用戶端請求。具體操作是Redis程序執行fork操作建立子程序,RDB持久化過程由子程序負責,完成後自動結束。阻塞隻發生在fork階段,一般時間很短。

  基本上 Redis 内部所有的RDB操作都是采用 bgsave 指令。

  ps:執行執行 flushall 指令,也會産生dump.rdb檔案,但裡面是空的,無意義

3、恢複資料

  将備份檔案 (dump.rdb) 移動到 redis 安裝目錄并啟動服務即可,redis就會自動加載檔案資料至記憶體了。Redis 伺服器在載入 RDB 檔案期間,會一直處于阻塞狀态,直到載入工作完成為止。

  擷取 redis 的安裝目錄可以使用 config get dir 指令

Redis詳解(六)------ RDB 持久化

4、停止 RDB 持久化

  有些情況下,我們隻想利用Redis的緩存功能,并不像使用 Redis 的持久化功能,那麼這時候我們最好停掉 RDB 持久化。可以通過上面講的在配置檔案 redis.conf 中,可以注釋掉所有的 save 行來停用儲存功能或者直接一個空字元串來實作停用:save ""

  也可以通過指令:

redis-cli config set save " "
      

5、RDB 的優勢和劣勢

  ①、優勢

  1.RDB是一個非常緊湊(compact)的檔案,它儲存了redis 在某個時間點上的資料集。這種檔案非常适合用于進行備份和災難恢複。

  2.生成RDB檔案的時候,redis主程序會fork()一個子程序來處理所有儲存工作,主程序不需要進行任何磁盤IO操作。

  3.RDB 在恢複大資料集時的速度比 AOF 的恢複速度要快。

  ②、劣勢

  1、RDB方式資料沒辦法做到實時持久化/秒級持久化。因為bgsave每次運作都要執行fork操作建立子程序,屬于重量級操作(記憶體中的資料被克隆了一份,大緻2倍的膨脹性需要考慮),頻繁執行成本過高(影響性能)

  2、RDB檔案使用特定二進制格式儲存,Redis版本演進過程中有多個格式的RDB版本,存在老版本Redis服務無法相容新版RDB格式的問題(版本不相容)

  3、在一定間隔時間做一次備份,是以如果redis意外down掉的話,就會丢失最後一次快照後的所有修改(資料有丢失)

6、RDB 自動儲存的原理

  Redis有個伺服器狀态結構:

struct redisService{
     //1、記錄儲存save條件的數組
     struct saveparam *saveparams;
     //2、修改計數器
     long long dirty;
     //3、上一次執行儲存的時間
     time_t lastsave;

}
      

  ①、首先看記錄儲存save條件的數組 saveparam,裡面每個元素都是一個 saveparams 結構:

struct saveparam{
     //秒數
     time_t seconds;
     //修改數
     int changes;
};      

  前面我們在 redis.conf 配置檔案中進行了關于save 的配置:

save 900 1:表示900 秒内如果至少有 1 個 key 的值變化,則儲存
save 300 10:表示300 秒内如果至少有 10 個 key 的值變化,則儲存
save 60 10000:表示60 秒内如果至少有 10000 個 key 的值變化,則儲存
      

  那麼伺服器狀态中的saveparam 數組将會是如下的樣子:

Redis詳解(六)------ RDB 持久化

  ②、dirty 計數器和lastsave 屬性

  dirty 計數器記錄距離上一次成功執行 save 指令或者 bgsave 指令之後,Redis伺服器進行了多少次修改(包括寫入、删除、更新等操作)。

  lastsave 屬性是一個時間戳,記錄上一次成功執行 save 指令或者 bgsave 指令的時間。

  通過這兩個指令,當伺服器成功執行一次修改操作,那麼dirty 計數器就會加 1,而lastsave 屬性記錄上一次執行save或bgsave的時間,Redis 伺服器還有一個周期性操作函數 severCron ,預設每隔 100 毫秒就會執行一次,該函數會周遊并檢查 saveparams 數組中的所有儲存條件,隻要有一個條件被滿足,那麼就會執行 bgsave 指令。

  執行完成之後,dirty 計數器更新為 0 ,lastsave 也更新為執行指令的完成時間。

   

作者:

YSOcean

出處:

http://www.cnblogs.com/ysocean/

本文版權歸作者所有,歡迎轉載,但未經作者同意不能轉載,否則保留追究法律責任的權利。