??redis作為一個(gè)高性能的key-value數(shù)據(jù)庫(kù),很大程度依賴于其基于內(nèi)存的數(shù)據(jù)操作。正因其數(shù)據(jù)存放在內(nèi)存中,若遇到服務(wù)異常退出、宕機(jī)等情況,無(wú)法將其數(shù)據(jù)進(jìn)行恢復(fù)。好在redis為我們提供了數(shù)據(jù)持久化方案,以解決上述問(wèn)題。
??redis在4.0版本之前提供兩種數(shù)據(jù)持久化方案,分別是RDB(全量)和AOF(增量),4.0之后提供了RDB-AOF混合持久化方案,充分利用了AOF和RDB各自優(yōu)勢(shì)。本文將就這三種方案從使用到底層原理進(jìn)行介紹。
1. RDB
??RDB是一種全量持久化方案,啟用RDB后,redis會(huì)在程序滿足用戶配置的規(guī)則時(shí),將內(nèi)存中的數(shù)據(jù)全量寫入文件系統(tǒng),已達(dá)到持久化的目的。
1.1 RDB配置
??redis持久化一般通過(guò)配置文件來(lái)進(jìn)行配置,默認(rèn)情況下(redis5.0.8),redis將內(nèi)存數(shù)據(jù)保存到dump.rdb的二進(jìn)制文件中,并且當(dāng)每900秒且1次寫操作,或每300秒10次寫操作,或每60秒10000次寫操作均會(huì)觸發(fā)RDB持久化。我可以通過(guò)修改配置文件來(lái)修改上述持久化規(guī)則。
#持久化存儲(chǔ)文件
dbfilename dump.rdb
#每900秒且1次寫操作
save 900 1
#每300秒10次寫操作
save 300 10
#每60秒10000次寫操作
save 60 10000
??同個(gè)配置文件中可以通過(guò)多條save命令來(lái)達(dá)到滿足指定條件中任一規(guī)則時(shí),觸發(fā)持久化。即當(dāng)存在多個(gè)save命令,他們?yōu)椤盎颉钡年P(guān)系。若不想開啟RDB持久化,只需要將所有的save保存策略注釋掉即可。
1.2 手動(dòng)生成RDB快照
??除了通過(guò)配置文件配置redis自動(dòng)生成RDB快照之外,我們還可以通過(guò)客戶端運(yùn)行save或bgsave命令,來(lái)手動(dòng)讓redis生成RDB快照文件。每次命令執(zhí)行后redis會(huì)將所有內(nèi)存數(shù)據(jù)生成一個(gè)RDB格式文件,并覆蓋原有的RDB快照文件。
??save是同步命令,bgsave是異步命令,bgsave會(huì)從redis主進(jìn)程fork出一個(gè)子進(jìn)程,專門用來(lái)生成RDB快照文件。save與bgsave對(duì)比如下:
| 命令 | save | bgsave |
|---|---|---|
| IO類型 | 同步 | 異步 |
| 是否阻塞redis其它命令 | 是 | 否 |
| 復(fù)雜度 | O(n) | O(n) |
| 優(yōu)點(diǎn) | 不會(huì)消耗額外內(nèi)存 | 不阻塞客戶端命令 |
| 缺點(diǎn) | 阻塞客戶端命令 | 需要fork子進(jìn)程 |
注意:通過(guò)1.1節(jié)配置文件來(lái)自動(dòng)生成RDB文件的方式,redis使用的是bgsave的方式。
2. AOF
??AOF(append only file)類似于Mysql的binlog,是一種增量持久化方案。AOF方案下,redis會(huì)將用戶操作的指令(只記錄寫命令)記錄到AOF文件。
2.1 AOF配置
??默認(rèn)情況下,redis不會(huì)開啟AOF持久化方案,我們可以通過(guò)在配置文件中添加以下配置開啟AOF:
#啟用AOF持久化
appendonly yes
#配置AOF存儲(chǔ)路徑
appendfilename "appendonly.aof"
??AOF有三種規(guī)則可供選擇,分別為always、everysec、no,用來(lái)設(shè)置redis將命令寫入AOF文件的時(shí)機(jī)。
#有新命令立即追加到 AOF 文件,速度慢,但數(shù)據(jù)安全性最高
appendfsync always
#每秒同步一次命令到文件中,速度較快(和使用 RDB 持久化差不多),在故障發(fā)生時(shí)最多只會(huì)丟失 1 秒鐘的數(shù)據(jù)
appendfsync everysec
#從不fsync,由操作系統(tǒng)自動(dòng)調(diào)度刷磁盤,速度最快,但安全性最低。
appendfsync no
??推薦在對(duì)數(shù)據(jù)安全性要求不高的場(chǎng)景下,使用everysec的fsync策略,這種策略可以同時(shí)兼顧性能和安全性。
2.2 AOF原理
??如本節(jié)開頭介紹,redis會(huì)在新的寫命令被執(zhí)行時(shí)記錄該命令,并按照用戶配置的策略將命令以RESP格式(redis客戶端與服務(wù)端通信協(xié)議格式)寫入文件系統(tǒng)。整個(gè)過(guò)程大致如下圖所示:

2.2.1 RESP
??RESP協(xié)議以 “*數(shù)字”標(biāo)記為開頭,表明指令共有多少段。每一段又以“$數(shù)字”標(biāo)記開頭,表明該段的內(nèi)容長(zhǎng)度,另外每個(gè)標(biāo)記和內(nèi)容均以過(guò)行符作為分隔。如下為執(zhí)行“set everlin 1”命令的AOF文件內(nèi)容:
*3
$3
set
$7
everlin
$1
1
2.2.1 AOF重寫
??隨著時(shí)間推移,AOF中記錄的指令會(huì)越來(lái)越多,文件占用空間越來(lái)越大,當(dāng)系統(tǒng)重啟去加載AOF時(shí),也會(huì)變得越慢。為了解決這一問(wèn)題,redis提供了AOF重寫的功能。AOF重寫的理論依據(jù)是,我們會(huì)對(duì)某個(gè)key進(jìn)行多次寫操作,而我們很容易找到一個(gè)命令,對(duì)這個(gè)key執(zhí)行后的結(jié)果,與前邊多次操作的結(jié)果一致。
例如執(zhí)行以下命令:
incr everlin
incr everlin
incr everlin
??在沒(méi)有進(jìn)行AOF重寫時(shí),AOF文件中的內(nèi)容如下:
*2
$4
incr
$7
everlin
*2
$4
incr
$7
everlin
*2
$4
incr
$7
everlin
??在redis進(jìn)行AOF重寫后,AOF文件內(nèi)容變?yōu)椋?/p>
*3
$3
set
$7
everlin
$1
4
??需要注意,重寫AOF文件的操作,redis并不是讀取舊的AOF文件后進(jìn)行成功學(xué),而是將整個(gè)內(nèi)存中的數(shù)據(jù)庫(kù)內(nèi)容用命令的方式重寫了一個(gè)新的AOF文件,這點(diǎn)和快照有點(diǎn)類似。此外,在redis4.0之后,若開啟了混合持久化方案,那么AOF重寫的數(shù)據(jù)將不再以RESP格式寫入,而是以RDB二進(jìn)制格式寫入AOF文件中。
AOF重寫也需要配置策略才能觸發(fā),如下兩個(gè)配置可以控制AOF自動(dòng)重寫頻率
#AOF文件至少要達(dá)到64M才進(jìn)行重寫
auto-aof-rewrite-min-size 64mb
#AOF文件自上一次重寫后文件大小增長(zhǎng)了100%,再次觸發(fā)重寫
auto-aof-rewrite-percentage 100
??我們還可以通過(guò)在客戶端使用bgrewriteaof命令,來(lái)對(duì)AOF進(jìn)行手動(dòng)重寫。redis通過(guò)fork一個(gè)子進(jìn)程進(jìn)行AOF重寫,因此,AOF重寫不會(huì)對(duì)redis正常命令處理產(chǎn)生太大影響。
3. RDB VS AOF
??通過(guò)1、2節(jié)的介紹,我們整理出RDB與AOF持久化方案的對(duì)比如下:
| 特點(diǎn) | RDB | AOF |
|---|---|---|
| 文件體積 | 小 | 大 |
| 性能影響 | 低 | 由同步策略決定(參見(jiàn)2.1) |
| 數(shù)據(jù)安全 | 容易丟數(shù)據(jù) | 由同步策略決定(參見(jiàn)2.1) |
| 恢復(fù)速度 | 快 | 慢 |
3.1 同時(shí)開啟RDB和AOF
??當(dāng)同時(shí)開啟RDB持久化和AOF持久化時(shí),兩種方案都會(huì)被redis啟用。但當(dāng)redis重啟時(shí),若同時(shí)存在RDB文件及AOF文件,redis會(huì)優(yōu)先選擇AOF文件進(jìn)行數(shù)據(jù)恢復(fù)。因?yàn)锳OF方案能保證數(shù)據(jù)更接近與上次redis停止時(shí)的數(shù)據(jù)。
4. 混合持久化方案
??前一節(jié)我們對(duì)比了RDB和AOF各自的優(yōu)缺點(diǎn),RDB占用存儲(chǔ)空間小,恢復(fù)速度快,AOF數(shù)據(jù)安全性更高,那有沒(méi)有方法可以發(fā)揮兩者的優(yōu)勢(shì),取長(zhǎng)補(bǔ)短呢。答案是有的,redis4.0之后提供了混合持久化方案,該方案基本與AOF方案一致,不同點(diǎn)在于,當(dāng)AOF重寫時(shí),以RDB格式對(duì)AOF進(jìn)行重寫。此時(shí)AOF的文件結(jié)構(gòu)如下:

??混合持久化方案提供了一種簡(jiǎn)單粗暴的方式,取長(zhǎng)補(bǔ)短,既保留了RDB文件體積小,恢復(fù)速度快的優(yōu)勢(shì),又解決了RDB持久化容易丟失數(shù)據(jù)的問(wèn)題。我們可以在配置文件中使用以下配置,啟用混合持久化:
aof-use-rdb-preamble yes
5. 小結(jié)
??本文分別介紹了RDB,AOF,混合持久化3種持久化方案:RDB文件體積小,恢復(fù)速度快,但容易丟失數(shù)據(jù);AOF可根據(jù)fsync策略提供不同的數(shù)據(jù)安全等級(jí),可以做到數(shù)據(jù)不丟失,但其恢復(fù)速度慢,redis提供了AOF重寫來(lái)壓縮其文件體積,提高恢復(fù)速度;混合持久化結(jié)合了RDB和AOF的優(yōu)勢(shì),在AOF重寫時(shí)以RDB格式將數(shù)據(jù)置于AOF文件開頭,大大提高了AOF的恢復(fù)速度,同時(shí)也保留了其數(shù)據(jù)安全性高的優(yōu)勢(shì)。建議在需要進(jìn)行持久化的場(chǎng)景下,選用混合持久化方案。