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

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

  因爲 Redis 是一個內存數據庫,所謂內存數據庫,就是將數據庫中的內容保存在內存中,這與傳統的MySQL,Oracle等關係型數據庫直接將內容保存到硬盤中相比,內存數據庫的讀寫效率比傳統數據庫要快的多(內存的讀寫效率遠遠大於硬盤的讀寫效率)。可是保存在內存中也隨之帶來了一個缺點,一旦斷電或者宕機,那麼內存數據庫中的數據將會所有丟失。redis

  爲了解決這個缺點,Redis提供了將內存數據持久化到硬盤,以及用持久化文件來恢復數據庫數據的功能。Redis 支持兩種形式的持久化,一種是RDB快照(snapshotting),另一種是AOF(append-only-file)。本篇博客先對 RDB 快照進行介紹。算法

一、RDB 簡介

  RDB是Redis用來進行持久化的一種方式,是把當前內存中的數據集快照寫入磁盤,也就是 Snapshot 快照(數據庫中全部鍵值對數據)。恢復時是將快照文件直接讀到內存裏。數據庫

二、觸發方式

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

①、自動觸發

  在 redis.conf 配置文件中的 SNAPSHOTTING 下,在這篇文章中咱們介紹過。緩存

  

  ①、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 ""app

  ②、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持久化的命令有兩種:

  一、save

  該命令會阻塞當前Redis服務器,執行save命令期間,Redis不能處理其餘命令,直到RDB過程完成爲止。

  顯然該命令對於內存比較大的實例會形成長時間阻塞,這是致命的缺陷,爲了解決此問題,Redis提供了第二種方式。

  二、bgsave

  執行該命令時,Redis會在後臺異步進行快照操做,快照同時還能夠響應客戶端請求。具體操做是Redis進程執行fork操做建立子進程,RDB持久化過程由子進程負責,完成後自動結束。阻塞只發生在fork階段,通常時間很短。

  基本上 Redis 內部全部的RDB操做都是採用 bgsave 命令。

  ps:執行執行 flushall 命令,也會產生dump.rdb文件,但裏面是空的,無心義

三、恢復數據

  將備份文件 (dump.rdb) 移動到 redis 安裝目錄並啓動服務便可,redis就會自動加載文件數據至內存了。Redis 服務器在載入 RDB 文件期間,會一直處於阻塞狀態,直到載入工做完成爲止。

  獲取 redis 的安裝目錄可使用 config get dir 命令

  

四、中止 RDB 持久化

  有些狀況下,咱們只想利用Redis的緩存功能,並不像使用 Redis 的持久化功能,那麼這時候咱們最好停掉 RDB 持久化。能夠經過上面講的在配置文件 redis.conf 中,能夠註釋掉全部的 save 行來停用保存功能或者直接一個空字符串來實現停用:save ""

  也能夠經過命令:

redis-cli config set save " "

五、RDB 的優點和劣勢

  ①、優點

  1.RDB是一個很是緊湊(compact)的文件,它保存了redis 在某個時間點上的數據集。這種文件很是適合用於進行備份和災難恢復。

  2.生成RDB文件的時候,redis主進程會fork()一個子進程來處理全部保存工做,主進程不須要進行任何磁盤IO操做。

  3.RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快。

  ②、劣勢

  一、RDB方式數據沒辦法作到實時持久化/秒級持久化。由於bgsave每次運行都要執行fork操做建立子進程,屬於重量級操做(內存中的數據被克隆了一份,大體2倍的膨脹性須要考慮),頻繁執行成本太高(影響性能)

  二、RDB文件使用特定二進制格式保存,Redis版本演進過程當中有多個格式的RDB版本,存在老版本Redis服務沒法兼容新版RDB格式的問題(版本不兼容)

  三、在必定間隔時間作一次備份,因此若是redis意外down掉的話,就會丟失最後一次快照後的全部修改(數據有丟失)

六、RDB 自動保存的原理

  Redis有個服務器狀態結構:

struct redisService{
     //一、記錄保存save條件的數組
     struct saveparam *saveparams;
     //二、修改計數器
     long long dirty;
     //三、上一次執行保存的時間
     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 數組將會是以下的樣子:

  

  ②、dirty 計數器和lastsave 屬性

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

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

  經過這兩個命令,當服務器成功執行一次修改操做,那麼dirty 計數器就會加 1,而lastsave 屬性記錄上一次執行save或bgsave的時間,Redis 服務器還有一個週期性操做函數 severCron ,默認每隔 100 毫秒就會執行一次,該函數會遍歷並檢查 saveparams 數組中的全部保存條件,只要有一個條件被知足,那麼就會執行 bgsave 命令。

  執行完成以後,dirty 計數器更新爲 0 ,lastsave 也更新爲執行命令的完成時間。

相關文章
相關標籤/搜索