Redis 相對於 Memcache 等其他的快取產品,有一個比較明顯的優點就是Redis 不僅僅支援簡單的key-value類型的數據,同時還提供list,set,zset ,hash等資料結構的儲存。這幾種豐富的資料類型我們花了兩篇文章進行了詳細的介紹,接下來我們要介紹 Redis 的另外一大優點——持久化。 (建議: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 也更新为执行命令的完成时间。
更多redis知识请关注redis数据库教程栏目。
以上是redis中RDB持久化詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!