Redis有兩種持久化的方式:快照(RDB 文件)和追加式文件(AOF 文件):
- RDB持久化方式會在一個特定的間隔保存那個時間點的一個數(shù)據(jù)快照。
- AOF持久化方式則會記錄每一個服務(wù)器收到的寫操作。在服務(wù)啟動時,這些記錄的操作會逐條執(zhí)行從而重建出原來的數(shù)據(jù)。寫操作命令記錄的格式跟Redis協(xié)議一致,以追加的方式進行保存。
- Redis的持久化是可以禁用的,就是說你可以讓數(shù)據(jù)的生命周期只存在于服務(wù)器的運行時間里。
- 兩種方式的持久化是可以同時存在的,但是當(dāng)Redis重啟時,AOF文件會被優(yōu)先用于重建數(shù)據(jù)。
補充:Redis 的存儲分為內(nèi)存存儲、磁盤存儲和log文件三部分,配置文件中有三個參數(shù)對其進行配置。
save seconds updates:在指定時間內(nèi),達到多少次更新操作時,就將數(shù)據(jù)同步到數(shù)據(jù)文件。這個可以多個條件配合,比如默認配置文件中的設(shè)置,就設(shè)置了三個條件。
appendonly yes/no:是否在每次更新操作后進行日志記錄,如果不開啟,可能會在斷電時導(dǎo)致一段時間內(nèi)的數(shù)據(jù)丟失。因為redis本身同步數(shù)據(jù)文件是按上面的save條件來同步的,所以有的數(shù)據(jù)會在一段時間內(nèi)只存在于內(nèi)存中。
appendfsyncno/always/everysec:no表示等操作系統(tǒng)進行數(shù)據(jù)緩存同步到磁盤,always表示每次更新操作后手動調(diào)用fsync()將數(shù)據(jù)寫到磁盤,everysec表示每秒同步一次。
一、RDB
工作原理
- Redis調(diào)用fork(),產(chǎn)生一個子進程。
- 子進程把數(shù)據(jù)寫到一個臨時的RDB文件。
- 當(dāng)子進程寫完新的RDB文件后,把舊的RDB文件替換掉。
優(yōu)點
- RDB文件是一個很簡潔的單文件,它保存了某個時間點的Redis數(shù)據(jù),很適合用于做備份。你可以設(shè)定一個時間點對RDB文件進行歸檔,這樣就能在需要的時候很輕易的把數(shù)據(jù)恢復(fù)到不同的版本。
- 基于上面所描述的特性,RDB很適合用于災(zāi)備。單文件很方便就能傳輸?shù)竭h程的服務(wù)器上。
- RDB的性能很好,需要進行持久化時,主進程會fork一個子進程出來,然后把持久化的工作交給子進程,自己不會有相關(guān)的I/O操作。
- 比起AOF,在數(shù)據(jù)量比較大的情況下,RDB的啟動速度更快。
缺點
- RDB容易造成數(shù)據(jù)的丟失。假設(shè)每5分鐘保存一次快照,如果Redis因為某些原因不能正常工作,那么從上次產(chǎn)生快照到Redis出現(xiàn)問題這段時間的數(shù)據(jù)就會丟失了。
- RDB使用
fork() 產(chǎn)生子進程進行數(shù)據(jù)的持久化,如果數(shù)據(jù)比較大的話可能就會花費點時間,造成Redis停止服務(wù)幾毫秒。如果數(shù)據(jù)量很大且CPU性能不是很好的時候,停止服務(wù)的時間甚至?xí)?秒。
文件路徑和名稱
默認Redis會把快照文件存儲為當(dāng)前目錄下一個名為dump.rdb 的文件。要修改文件的存儲路徑和名稱,可以通過修改配置文件redis.conf 實現(xiàn):
# RDB文件名,默認為dump.rdb。
dbfilename dump.rdb
# 文件存放的目錄,AOF文件同樣存放在此目錄下。默認為當(dāng)前工作目錄。
dir ./
保存點(RDB的啟用和禁用)
你可以配置保存點,使Redis如果在每N秒后數(shù)據(jù)發(fā)生了M次改變就保存快照文件。例如下面這個保存點配置表示每60秒,如果數(shù)據(jù)發(fā)生了1000次以上的變動,Redis就會自動保存快照文件:
save 60 1000
保存點可以設(shè)置多個,Redis的配置文件就默認設(shè)置了3個保存點:
# 格式為:save <seconds> <changes>
# 可以設(shè)置多個。
save 900 1 #900秒后至少1個key有變動
save 300 10 #300秒后至少10個key有變動
save 60 10000 #60秒后至少10000個key有變動
如果想禁用快照保存的功能,可以通過注釋掉所有"save"配置達到,或者在最后一條"save"配置后添加如下的配置:
save ""
錯誤處理
默認情況下,如果Redis在后臺生成快照的時候失敗,那么就會停止接收數(shù)據(jù),目的是讓用戶能知道數(shù)據(jù)沒有持久化成功。但是如果你有其他的方式可以監(jiān)控到Redis及其持久化的狀態(tài),那么可以把這個功能禁止掉。
stop-writes-on-bgsave-error yes
數(shù)據(jù)壓縮
默認Redis會采用LZF 對數(shù)據(jù)進行壓縮。如果你想節(jié)省點CPU的性能,你可以把壓縮功能禁用掉,但是數(shù)據(jù)集就會比沒壓縮的時候要打。
rdbcompression yes
數(shù)據(jù)校驗
從版本5的RDB的開始,一個CRC64 的校驗碼會放在文件的末尾。這樣更能保證文件的完整性,但是在保存或者加載文件時會損失一定的性能(大概10%)。如果想追求更高的性能,可以把它禁用掉,這樣文件在寫入校驗碼時會用0 替代,加載的時候看到0 就會直接跳過校驗。
rdbchecksum yes
手動生成快照
Redis提供了兩個命令用于手動生成快照。
SAVE
SAVE命令會使用同步的方式生成RDB快照文件,這意味著在這個過程中會阻塞所有其他客戶端的請求。因此不建議在生產(chǎn)環(huán)境使用這個命令,除非因為某種原因需要去阻止Redis使用子進程進行后臺生成快照(例如調(diào)用fork(2) 出錯)。
BGSAVE
BGSAVE命令使用后臺的方式保存RDB文件,調(diào)用此命令后,會立刻返回OK 返回碼。Redis會產(chǎn)生一個子進程進行處理并立刻恢復(fù)對客戶端的服務(wù)。在客戶端我們可以使用LASTSAVE命令查看操作是否成功。
127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379> LASTSAVE
(integer) 1433936394
配置文件里禁用了快照生成功能不影響SAVE 和BGSAVE 命令的效果
二、AOF
快照并不是很可靠。如果你的電腦突然宕機了,或者電源斷了,又或者不小心殺掉了進程,那么最新的數(shù)據(jù)就會丟失。而AOF文件則提供了一種更為可靠的持久化方式。每當(dāng)Redis接受到會修改數(shù)據(jù)集的命令時,就會把命令追加到AOF文件里,當(dāng)你重啟Redis時,AOF里的命令會被重新執(zhí)行一次,重建數(shù)據(jù)。
優(yōu)點
- 比RDB可靠。你可以制定不同的fsync策略:不進行fsync、每秒fsync一次和每次查詢進行fsync。默認是每秒fsync一次。這意味著你最多丟失一秒鐘的數(shù)據(jù)。
- AOF日志文件是一個純追加的文件。就算是遇到突然停電的情況,也不會出現(xiàn)日志的定位或者損壞問題。甚至如果因為某些原因(例如磁盤滿了)命令只寫了一半到日志文件里,我們也可以用
redis-check-aof 這個工具很簡單的進行修復(fù)。
- 當(dāng)AOF文件太大時,Redis會自動在后臺進行重寫。重寫很安全,因為重寫是在一個新的文件上進行,同時Redis會繼續(xù)往舊的文件追加數(shù)據(jù)。新文件上會寫入能重建當(dāng)前數(shù)據(jù)集的最小操作命令的集合。當(dāng)新文件重寫完,Redis會把新舊文件進行切換,然后開始把數(shù)據(jù)寫到新文件上。
- AOF把操作命令以簡單易懂的格式一條接一條的保存在文件里,很容易導(dǎo)出來用于恢復(fù)數(shù)據(jù)。例如我們不小心用
FLUSHALL 命令把所有數(shù)據(jù)刷掉了,只要文件沒有被重寫,我們可以把服務(wù)停掉,把最后那條命令刪掉,然后重啟服務(wù),這樣就能把被刷掉的數(shù)據(jù)恢復(fù)回來。
缺點
- 在相同的數(shù)據(jù)集下,AOF文件的大小一般會比RDB文件大。
- 在某些fsync策略下,AOF的速度會比RDB慢。通常fsync設(shè)置為每秒一次就能獲得比較高的性能,而在禁止fsync的情況下速度可以達到RDB的水平。
- 在過去曾經(jīng)發(fā)現(xiàn)一些很罕見的BUG導(dǎo)致使用AOF重建的數(shù)據(jù)跟原數(shù)據(jù)不一致的問題。
啟用AOF
把配置項appendonly 設(shè)為yes :
appendonly yes
文件路徑和名稱
# 文件存放目錄,與RDB共用。默認為當(dāng)前工作目錄。
dir ./
# 默認文件名為appendonly.aof
appendfilename "appendonly.aof"
可靠性
你可以配置Redis調(diào)用fsync的頻率,有三個選項:
- 每當(dāng)有新命令追加到AOF的時候調(diào)用fsync。速度最慢,但是最安全。
- 每秒fsync一次。速度快(2.4版本跟快照方式速度差不多),安全性不錯(最多丟失1秒的數(shù)據(jù))。
- 從不fsync,交由系統(tǒng)去處理。這個方式速度最快,但是安全性一般。
推薦使用每秒fsync一次的方式(默認的方式),因為它速度快,安全性也不錯。相關(guān)配置如下:
# appendfsync always
appendfsync everysec
# appendfsync no
日志重寫
隨著寫操作的不斷增加,AOF文件會越來越大。例如你遞增一個計數(shù)器100次,那么最終結(jié)果就是數(shù)據(jù)集里的計數(shù)器的值為最終的遞增結(jié)果,但是AOF文件里卻會把這100次操作完整的記錄下來。而事實上要恢復(fù)這個記錄,只需要1個命令就行了,也就是說AOF文件里那100條命令其實可以精簡為1條。所以Redis支持這樣一個功能:在不中斷服務(wù)的情況下在后臺重建AOF文件。
工作原理如下:
- Redis調(diào)用fork(),產(chǎn)生一個子進程。
- 子進程把新的AOF寫到一個臨時文件里。
- 主進程持續(xù)把新的變動寫到內(nèi)存里的buffer,同時也會把這些新的變動寫到舊的AOF里,這樣即使重寫失敗也能保證數(shù)據(jù)的安全。
- 當(dāng)子進程完成文件的重寫后,主進程會獲得一個信號,然后把內(nèi)存里的buffer追加到子進程生成的那個新AOF里。
- Redis
我們可以通過配置設(shè)置日志重寫的條件:
# Redis會記住自從上一次重寫后AOF文件的大?。ㄈ绻訰edis啟動后還沒重寫過,則記住啟動時使用的AOF文件的大?。?。
# 如果當(dāng)前的文件大小比起記住的那個大小超過指定的百分比,則會觸發(fā)重寫。
# 同時需要設(shè)置一個文件大小最小值,只有大于這個值文件才會重寫,以防文件很小,但是已經(jīng)達到百分比的情況。
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
要禁用自動的日志重寫功能,我們可以把百分比設(shè)置為0:
auto-aof-rewrite-percentage 0
Redis 2.4以上才可以自動進行日志重寫,之前的版本需要手動運行BGREWRITEAOF這個命令。
數(shù)據(jù)損壞修復(fù)
如果因為某些原因(例如服務(wù)器崩潰)AOF文件損壞了,導(dǎo)致Redis加載不了,可以通過以下方式進行修復(fù):
從RDB切換到AOF
這里只說Redis >= 2.2版本的方式:
第二條命令是用來禁用RDB的持久化方式,但是這不是必須的,因為你可以同時啟用兩種持久化方式。
記得對配置文件redis.conf 進行編輯啟用AOF,因為命令行方式修改配置在重啟Redis后就會失效。
Redis 配置文件默認情況下是開啟 rdb模式的寫入磁盤備份的.
1.默認開啟的情況下是使用Master傳輸rdb文件到slave進行主從同步。
2.禁用rdb和aof模式在不生成rdb文件的情況下也可以實現(xiàn)主從同步,前提是master,slave服務(wù)器都在運行中的時候,這個種情況下master只是把緩沖區(qū)中的set 操作傳輸?shù)絪lave端,slave端再執(zhí)行set命令實現(xiàn)主從同步。
3.當(dāng)禁用master,slave rdb模式的情況下,shutdown slave 端,再重啟時,會去連接master端同步數(shù)據(jù),master端會生成dump.rdb文件,然后傳給slave端,salve端同時也會生成dump.rdb文件。
總結(jié):master,slvae端可以在配置文件中可以禁用rdb模式,這時數(shù)據(jù)只存在內(nèi)存中。當(dāng)slave 端重起時,會連接master端,maser端會把內(nèi)存中數(shù)據(jù)生成到dump.rdb文件,然后把rdb文件和緩沖區(qū)中的set命令然后傳給slave,slave也會生成dump.rdb文件。如果master服務(wù)先掛了,那么就是災(zāi)難性的了。因為這個時候master端還沒有dump.rdb文件,服務(wù)啟動后找不到rdb文件載入到內(nèi)存中。slave端會去連接master端同步數(shù)據(jù),把空數(shù)據(jù)同步回來覆蓋原先的已有數(shù)據(jù)。造成master,slvae端都沒有了緩存數(shù)據(jù)。
|