Redis的持久化

因爲Redis是內存數據庫,它的所有信息都存儲在內存中,要是數據庫出現問題,可能丟失所有數據。所以爲了將數據永久保存下來,Redis提供了持久化的方式

Redis有兩種持久化的方式:快照(RDB文件)和追加式文件(AOF文件):

  1. RDB持久化方式會在一個特定的間隔保存那個時間點的一個數據快照。
  2. AOF持久化方式則會記錄每一個服務器收到的寫操作。在服務啓動時,這些記錄的操作會逐條執行從而重建出原來的數據。寫操作命令記錄的格式跟Redis協議一致,以追加的方式進行保存。

Redis的持久化是可以禁用的,就是說你可以讓數據的生命週期只存在於服務器的運行時間裏。兩種方式的持久化是可以同時存在的,但是當Redis重啓時,AOF文件會被優先用於重建數據。

一、RDB

重點內容
(將數據庫中的鍵值對及狀態保存在持久化文件中)
工作原理:

  1. Redis調用fork(),產生一個子進程。
  2. 子進程把數據寫到一個臨時的RDB文件。
  3. 當子進程寫完新的RDB文件後,把舊的RDB文件替換掉。

優點:

  • RDB文件是一個很簡潔的單文件,它保存了某個時間點的Redis數據,很適合用於做備份。你可以設定一個時間點對RDB文件進行歸檔,這樣就能在需要的時候很輕易的把數據恢復到不同的版本。
  • 基於上面所描述的特性,RDB很適合用於災備。單文件很方便就能傳輸到遠程的服務器上。
  • RDB的性能很好,需要進行持久化時,主進程會fork一個子進程出來,然後把持久化的工作交給子進程,自己不會有相關的I/O操作。
  • 比起AOF,在數據量比較大的情況下,RDB的啓動速度更快。

缺點:

  • RDB容易造成數據的丟失。假設每5分鐘保存一次快照,如果Redis因爲某些原因不能正常工作,那麼從上次產生快照到Redis出現問題這段時間的數據就會丟失了。
  • RDB使用fork()產生子進程進行數據的持久化,如果數據比較大的話可能就會花費點時間,造成Redis停止服務幾毫秒。如果數據量很大且CPU性能不是很好的時候,停止服務的時間甚至會到1秒。

文件路徑和名稱:

默認Redis會把快照文件存儲爲當前目錄下一個名爲dump.rdb的文件。要修改文件的存儲路徑和名稱,可以通過修改配置文件redis.conf實現:
  • RDB文件名,默認爲dump.rdb。
  • dbfilename dump.rdb
  • 文件存放的目錄,AOF文件同樣存放在此目錄下。默認爲當前工作目錄。 dir ./

保存點(RDB的啓用和禁用)

你可以配置保存點,使Redis如果在每N秒後數據發生了M次改變就保存快照文件。例如下面這個保存點配置表示每60秒,如果數據發生了1000次以上的變動,Redis就會自動保存快照文件:
save 60 1000
保存點可以設置多個,Redis的配置文件就默認設置了3個保存點:

  格式爲:save seconds changes

可以設置多個。

save 900 1 #900秒後至少1個key有變動
save 300 10 #300秒後至少10個key有變動
save 60 10000 #60秒後至少10000個key有變動

如果想禁用快照保存的功能,可以通過註釋掉所有”save”配置達到,或者在最後一條”save”配置後添加如下的配置: save “”

錯誤處理
默認情況下,如果Redis在後臺生成快照的時候失敗,那麼就會停止接收數據,目的是讓用戶能知道數據沒有持久化成功。但是如果你有其他的方式可以監控到Redis及其持久化的狀態,那麼可以把這個功能禁止掉。
stop-writes-on-bgsave-error yes
數據壓縮
默認Redis會採用LZF對數據進行壓縮。如果你想節省點CPU的性能,你可以把壓縮功能禁用掉,但是數據集就會比沒壓縮的時候要打。
rdbcompression yes
數據校驗
從版本5的RDB的開始,一個CRC64的校驗碼會放在文件的末尾。這樣更能保證文件的完整性,但是在保存或者加載文件時會損失一定的性能(大概10%)。如果想追求更高的性能,可以把它禁用掉,這樣文件在寫入校驗碼時會用0替代,加載的時候看到0就會直接跳過校驗。
rdbchecksum yes
手動生成快照

Redis提供了兩個命令用於手動生成快照:

SAVE

  • SAVE命令會使用同步的方式生成RDB快照文件,這意味着在這個過程中會阻塞所有其他客戶端的請求。因此不建議在生產環境使用這個命令,除非因爲某種原因需要去阻止Redis使用子進程進行後臺生成快照(例如調用fork(2)出錯)。

BGSAVE

  • BGSAVE命令使用後臺的方式保存RDB文件,調用此命令後,會立刻返回OK返回碼。Redis會產生一個子進程進行處理並立刻恢復對客戶端的服務。在客戶端我們可以使用LASTSAVE命令
查看操作是否成功。
127.0.0.1:6379> BGSAVEBackground saving started
127.0.0.1:6379> LASTSAVE
(integer) 1433936394

配置文件裏禁用了快照生成功能不影響SAVE和BGSAVE命令的效果。

2、AOF

(保存的是服務器所執行過的所有寫命令)

快照並不是很可靠。如果你的電腦突然宕機了,或者電源斷了,又或者不小心殺掉了進程,那麼最新的數據就會丟失。而AOF文件則提供了一種更爲可靠的持久化方式。每當Redis接受到會修改數據集的命令時,就會把命令追加到AOF文件裏,當你重啓Redis時,AOF裏的命令會被重新執行一次,重建數據。

優點:

  1. 比RDB可靠。你可以制定不同的fsync策略:不進行fsync、每秒fsync一次和每次查詢進行fsync。默認是每秒fsync一次。這意味着你最多丟失一秒鐘的數據。
  2. AOF日誌文件是一個純追加的文件。就算是遇到突然停電的情況,也不會出現日誌的定位或者損壞問題。甚至如果因爲某些原因(例如磁盤滿了)命令只寫了一半到日誌文件裏,我們也可以用redis-check-aof這個工具很簡單的進行修復。
  3. 當AOF文件太大時,Redis會自動在後臺進行重寫。重寫很安全,因爲重寫是在一個新的文件上進行,同時Redis會繼續往舊的文件追加數據。新文件上會寫入能重建當前數據集的最小操作命令的集合。當新文件重寫完,Redis會把新舊文件進行切換,然後開始把數據寫到新文件上。
  4. AOF把操作命令以簡單易懂的格式一條接一條的保存在文件裏,很容易導出來用於恢復數據。例如我們不小心用FLUSHALL命令把所有數據刷掉了,只要文件沒有被重寫,我們可以把服務停掉,把最後那條命令刪掉,然後重啓服務,這樣就能把被刷掉的數據恢復回來。

缺點:

  1. 在相同的數據集下,AOF文件的大小一般會比RDB文件大。
  2. 在某些fsync策略下,AOF的速度會比RDB慢。通常fsync設置爲每秒一次就能獲得比較高的性能,而在禁止fsync的情況下速度可以達到RDB的水平。

在過去曾經發現一些很罕見的BUG導致使用AOF重建的數據跟原數據不一致的問題。

啓用AOF
把配置項appendonly設爲yes:
appendonly yes
文件路徑和名稱
文件存放目錄,與RDB共用。默認爲當前工作目錄。
dir ./
默認文件名爲appendonly.aof
appendfilename "appendonly.aof"

可靠性
你可以配置Redis調用fsync的頻率,有三個選項:

  1. 每當有新命令追加到AOF的時候調用fsync。速度最慢,但是最安全。
  2. 每秒fsync一次。速度快(2.4版本跟快照方式速度差不多),安全性不錯(最多丟失1秒的數據)。
  3. 從不fsync,交由系統去處理。這個方式速度最快,但是安全性一般。

推薦使用每秒fsync一次的方式(默認的方式),因爲它速度快,安全性也不錯。相關配置如下:

appendfsync always
appendfsync everysec# appendfsync no

日誌重寫

隨着寫操作的不斷增加,AOF文件會越來越大。例如你遞增一個計數器100次,那麼最終結果就是數據集裏的計數器的值爲最終的遞增結果,但是AOF文件裏卻會把這100次操作完整的記錄下來。而事實上要恢復這個記錄,只需要1個命令就行了,也就是說AOF文件裏那100條命令其實可以精簡爲1條。所以Redis支持這樣一個功能:在不中斷服務的情況下在後臺重建AOF文件。

工作原理如下:

Redis調用fork(),產生一個子進程。
子進程把新的AOF寫到一個臨時文件裏。
主進程持續把新的變動寫到內存裏的buffer,同時也會把這些新的變動寫到舊的AOF裏,這樣即使重寫失敗也能保證數據的安全。
當子進程完成文件的重寫後,主進程會獲得一個信號,然後把內存裏的buffer追加到子進程生成的那個新AOF裏

Redis
我們可以通過配置設置日誌重寫的條件:
Redis會記住自從上一次重寫後AOF文件的大小(如果自Redis啓動後還沒重寫過,則記住啓動時使用的AOF文件的大小)。# 如果當前的文件大小比起記住的那個大小超過指定的百分比,則會觸發重寫。# 同時需要設置一個文件大小最小值,只有大於這個值文件纔會重寫,以防文件很小,但是已經達到百分比的情況。

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

要禁用自動的日誌重寫功能,我們可以把百分比設置爲0:

auto-aof-rewrite-percentage 0

Redis 2.4以上纔可以自動進行日誌重寫,之前的版本需要手動運行BGREWRITEAOF這個命令。 數據損壞修復
如果因爲某些原因(例如服務器崩潰)AOF文件損壞了,導致Redis加載不了,可以通過以下方式進行修復: 備份AOF文件。

使用redis-check-aof命令修復原始的AOF文件:

$ redis-check-aof --fix

可以使用diff -u命令看下兩個文件的差異。
使用修復過的文件重啓Redis服務。
從RDB切換到AOF
這裏只說Redis >= 2.2版本的方式:
備份一個最新的dump.rdb的文件,並把備份文件放在一個安全的地方。

運行以下兩條命令:

$ redis-cli config set appendonly yes
$ redis-cli config set save ""
  • 確保數據跟切換前一致。
  • 確保數據正確的寫到AOF文件裏。
  • 第二條命令是用來禁用RDB的持久化方式,但是這不是必須的,因爲你可以同時啓用兩種持久化方式。
  • 記得對配置文件redis.conf進行編輯啓用AOF,因爲命令行方式修改配置在重啓Redis後就會失效。

建議的備份方法:

  1. 創建一個定時任務,每小時和每天創建一個快照,保存在不同的文件夾裏。
  2. 定時任務運行時,把太舊的文件進行刪除。例如只保留48小時的按小時創建的快照和一到兩個月的按天創建的快照。
  3. 每天確保一次把快照文件傳輸到數據中心外的地方進行保存,至少不能保存在Redis服務所在的服務器。
發佈了36 篇原創文章 · 獲贊 149 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章