淺談Redis的兩種持久化機制

前言

衆所周知,redis是一個內存數據庫,既然是將數據保存在內存中,上下線之後數據自然就會丟失,在我們的業務中,這種情況當然是不允許發生的,所以這時候就需要涉及到redis的持久化機制

redis可以手動開啓持久化,來讓內存中的數據持久化到磁盤上,redis提供了以下兩種持久化方案:

  • RDB快照
  • AOF日誌

接下來我們就要針對這兩種方式來做一個講解

RDB快照

rdb快照的原理是對redis中的數據進行週期性的持久化,也可以理解爲redis每隔一段時間就把當前內存數據的狀態持久化到磁盤中

這個具體的操作並不是由工作進程來完成的,redis會調用fork函數來創建一個子進程,父進程會正常執行客戶端發來的請求操作,而子進程會把當前的數據庫快照寫入到臨時文件中,最後替換原有的文件(默認爲dump.rdb)

由於操作系統的copy-on-write機制,父子進程是共享物理頁面的,當父進程處理寫請求時,操作系統爲父進程要修改的頁面創建一個副本,所以子進程地址空間的數據只是當前時刻整個數據庫的一個快照,也這就是把這種方式叫做rdb快照的原因

這種方式的優點很明顯:

  • RDB模式下會不斷產生快照文件,均代表某一時刻redis中的數據,可以用作冷備份
  • 採用子進程來執行磁盤IO,寫入快照的時候對redis的影響非常小,可以保持redis的高性能
  • 重啓和恢復redis數據的速度很快

但是其也有缺點:

  • 如果在兩次快照之間發生宕機,則其間寫入的數據會丟失
  • 每次fork的時候,如果數據很大,則會產生一定時間的服務暫停

redis是默認開啓這種持久化方式的,可以打開redis.conf文件,如果是window系統就打開redis.window.conf(redis.windows-service.conf文件是作爲系統服務啓動時加載的配置文件,如果你設置redis爲系統服務,就打開這一個),會發現下面這些配置:

save 900 1
save 300 10
save 60 10000

我們拿save 900 1這條配置來舉例,其含義就是在900秒內,如果至少有1個key值發生了變化,就進行內存快照,我們查看默認的這些配置也可以發現,這些save語句是可以同時出現的,所以你可以配置很多這樣的rdb快照設置

AOF日誌

看名字應該能猜得出,這種持久化模式是採用日誌來進行的,aof模式通過把每條指令追加到日誌文件中(默認爲appendonly.aof文件),當redis重啓後,通過回放aof日誌文件中的操作來實現數據集的恢復

開啓了aof持久化模式後,redis會將所有收到的修改命令通過write函數追加到日誌文件中,具體的執行可以設置以下3種:

  • always:每次有修改操作就強制寫入
  • everysec:每秒鐘強制寫入(推薦使用)
  • no:不主動進行持久化,將數據存放在操作系統中,一般linux每30分鐘刷新一次數據

這三種模式分別對應配置文件中的appendfsync alwaysappendfsync everysec,和appendfsync no

接着我們可以看一下aof日誌的內容,這裏截取了一小段我測試的aof文件:

set
$3
bbb
$3
aaa
*3
$3
set
$3
aaa
$3
ccc
*2
$3
del
$3
aaa

可以看出,所有的修改命令都是通過命令符-數據庫名-key值這樣的順序來保存的,可讀性也很高

但是aof日誌依然有一個問題,如果我們反覆地執行set操作,那麼aof日誌中就會重複地保存這些不必要的操作,因爲這些命令最終的執行結果和一個set命令的執行結果沒有任何區別,那怎麼解決這種數據冗餘問題呢?

其實這一點redis開發人員也想到了,redis提供了bgrewriteaof命令,收到此命令的redis服務器會自動fork出一個子進程,這個子進程會根據內存中的數據快照,來創建一個用於恢復當期數據的最小日誌文件,當寫入完成後,子進程會向父進程發送信號,然後父進程把緩存中的修改命令也寫入這個臨時文件中,並用這個臨時文件來替換原aof文件

這份生成的aof文件你會發現幾乎都是set操作,而且基本不會出現對一個值重複的set命令,所以恢復起來也相當迅速

aof模式的優點如下:

  • 可讀性非常高,如果發生了誤操作,可以在rewrite操作之前拷貝一份aof日誌文件,將其中的誤操作刪去,然後替換原有文件即可,不影響redis的恢復讀取,可以用來作爲緊急恢復
  • 丟失數據的機率很低,即使丟失也不會有太大影響(如果設置了每秒備份,則最多會丟失1s內寫入的數據)

但是也依然有缺點:

  • aof文件一般大於rbd文件
  • 根據選擇的fsync策略的不同,aof的速度可能會慢於rdb
  • 在寫入負載很大的情況下,aof不能提供最大延遲的保證,而rbd可以
  • 有機率發生不能完全恢復redis數據的bug

使用場景

在平常使用時,我們不能說哪種就是最好的,而要根據實際情況來選擇,這裏我提供一些選擇的建議:

  • 如果你可以允許當發生宕機時有幾分鐘的數據丟失,那麼就使用RDB快照模式,它可以讓你更快地重啓redis
  • 其餘情況均推薦採用RDB+AOF的模式

沒錯,在使用時可以同時配置rdb和aof兩種模式,redis官方也推薦我們這麼做,aof爲主,rdb爲輔,aof記錄日誌,rdb做數據庫備份,以及aof引擎失效後的替代

總結

持久化的講解到這裏基本就結束了,這裏僅僅是帶大家簡要了解了一下redis持久化的內容,本文一部分是個人的理解、總結與實踐,剩餘的部分均參考Redis Persistence – Redis(如今網絡上幾乎全部的有關redis持久化的博客都是這個網站的內容),如果有什麼錯誤歡迎指正

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章