因爲Redis是內存數據庫,它的所有信息都存儲在內存中,要是數據庫出現問題,可能丟失所有數據。所以爲了將數據永久保存下來,Redis提供了持久化的方式
Redis有兩種持久化的方式:快照(RDB文件)和追加式文件(AOF文件):
- RDB持久化方式會在一個特定的間隔保存那個時間點的一個數據快照。
- AOF持久化方式則會記錄每一個服務器收到的寫操作。在服務啓動時,這些記錄的操作會逐條執行從而重建出原來的數據。寫操作命令記錄的格式跟Redis協議一致,以追加的方式進行保存。
Redis的持久化是可以禁用的,就是說你可以讓數據的生命週期只存在於服務器的運行時間裏。兩種方式的持久化是可以同時存在的,但是當Redis重啓時,AOF文件會被優先用於重建數據。
一、RDB
重點內容
(將數據庫中的鍵值對及狀態保存在持久化文件中)
工作原理:
- Redis調用fork(),產生一個子進程。
- 子進程把數據寫到一個臨時的RDB文件。
- 當子進程寫完新的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裏的命令會被重新執行一次,重建數據。
優點:
- 比RDB可靠。你可以制定不同的fsync策略:不進行fsync、每秒fsync一次和每次查詢進行fsync。默認是每秒fsync一次。這意味着你最多丟失一秒鐘的數據。
- AOF日誌文件是一個純追加的文件。就算是遇到突然停電的情況,也不會出現日誌的定位或者損壞問題。甚至如果因爲某些原因(例如磁盤滿了)命令只寫了一半到日誌文件裏,我們也可以用redis-check-aof這個工具很簡單的進行修復。
- 當AOF文件太大時,Redis會自動在後臺進行重寫。重寫很安全,因爲重寫是在一個新的文件上進行,同時Redis會繼續往舊的文件追加數據。新文件上會寫入能重建當前數據集的最小操作命令的集合。當新文件重寫完,Redis會把新舊文件進行切換,然後開始把數據寫到新文件上。
- AOF把操作命令以簡單易懂的格式一條接一條的保存在文件裏,很容易導出來用於恢復數據。例如我們不小心用FLUSHALL命令把所有數據刷掉了,只要文件沒有被重寫,我們可以把服務停掉,把最後那條命令刪掉,然後重啓服務,這樣就能把被刷掉的數據恢復回來。
缺點:
- 在相同的數據集下,AOF文件的大小一般會比RDB文件大。
- 在某些fsync策略下,AOF的速度會比RDB慢。通常fsync設置爲每秒一次就能獲得比較高的性能,而在禁止fsync的情況下速度可以達到RDB的水平。
在過去曾經發現一些很罕見的BUG導致使用AOF重建的數據跟原數據不一致的問題。
啓用AOF
把配置項appendonly設爲yes:
appendonly yes
文件路徑和名稱
文件存放目錄,與RDB共用。默認爲當前工作目錄。
dir ./
默認文件名爲appendonly.aof
appendfilename "appendonly.aof"
可靠性
你可以配置Redis調用fsync的頻率,有三個選項:
- 每當有新命令追加到AOF的時候調用fsync。速度最慢,但是最安全。
- 每秒fsync一次。速度快(2.4版本跟快照方式速度差不多),安全性不錯(最多丟失1秒的數據)。
- 從不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後就會失效。
建議的備份方法:
- 創建一個定時任務,每小時和每天創建一個快照,保存在不同的文件夾裏。
- 定時任務運行時,把太舊的文件進行刪除。例如只保留48小時的按小時創建的快照和一到兩個月的按天創建的快照。
- 每天確保一次把快照文件傳輸到數據中心外的地方進行保存,至少不能保存在Redis服務所在的服務器。