前面我們說過,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 ""
也可以通過指令:
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 數組将會是如下的樣子:
②、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/本文版權歸作者所有,歡迎轉載,但未經作者同意不能轉載,否則保留追究法律責任的權利。