1. 程式人生 > 實用技巧 >Redis詳解(六)- RDB 持久化

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 下。

  

  ①、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 命令

  

  載入的標識是如下命令:

  

回到頂部

4、停止 RDB 持久化

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

  也可以通過命令:

1 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有個伺服器狀態結構:

1 2 3 4 5 6 7 8 9 structredisService{ //1、記錄儲存save條件的陣列 structsaveparam *saveparams; //2、修改計數器 longlongdirty; //3、上一次執行儲存的時間 time_tlastsave; }

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

1 2 3 4 5 6 structsaveparam{ //秒數 time_tseconds; //修改數 intchanges; };

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

1 2 3 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 也更新為執行命令的完成時間。