一、Redis持久化必要性
Redis作為內(nèi)存數(shù)據(jù)庫,為了應(yīng)對(duì)因進(jìn)程意外退出造成的數(shù)據(jù)丟失,Redis提供了RDB和AOF兩種持久化方式,用于將數(shù)據(jù)從內(nèi)存持久化到硬盤文件。Redis進(jìn)程意外退出后重啟時(shí),Redis會(huì)自動(dòng)利用持久化文件恢復(fù)數(shù)據(jù)。
- RDB (Redis database)快照(snapshot),全量備份,單一文件,文件總量小,恢復(fù)快,但數(shù)據(jù)存在丟失。
- AOF(Append file only), 增量備份,丟失少量數(shù)據(jù),會(huì)影響實(shí)時(shí)性能。
二、RDB
觸發(fā)機(jī)制:
- 手動(dòng)觸發(fā)
- save 會(huì)阻塞客戶端請(qǐng)求命令,影響業(yè)務(wù),線上環(huán)境不建議使用。
127.0.0.1:6379> save OK
- bgsave 是對(duì)save做的優(yōu)化,不會(huì)阻塞客戶端請(qǐng)求,但是fork過程會(huì)造成阻塞(后面詳細(xì)說明)。這也是目前RDB自動(dòng)持久化的方式。
127.0.0.1:6379> bgsave Background saving started
- 自動(dòng)觸發(fā)
- 配置redis.conf中的save備份規(guī)則,或者redis-server啟動(dòng)后,通過config set命令配置save規(guī)則。
127.0.0.1:6379> config set save "3600 1 300 100 60 10000" OK
- save m n表示,表示每m秒內(nèi)數(shù)據(jù)集產(chǎn)生了n次修改,將自動(dòng)觸發(fā)RDB持久化。
- 關(guān)閉該功能,將save設(shè)置為""
config set save ""
- flushall,該命令會(huì)產(chǎn)生空的.rdb文件。
- debug reload, 執(zhí)行該命令會(huì)自動(dòng)觸發(fā)save操作。
- shutdown,執(zhí)行shudown操作,會(huì)自動(dòng)備份,生成.rdb文件。
RDB過程:
-
RDB過程如下:
- 執(zhí)行bgsave,判斷當(dāng)前是否存在RDB子進(jìn)程,如果存在,則返回。
- 父進(jìn)程通過fork操作創(chuàng)建子進(jìn)程,父進(jìn)程造成一定阻塞,通過info命令可以查看latest_fork_usec表示上次fork操作用時(shí)。
- 父進(jìn)程執(zhí)行完fork后,bgsave命令返回“Background saving started”,并不再阻塞,繼續(xù)響應(yīng)客戶端請(qǐng)求。
- 子進(jìn)程創(chuàng)建rdb文件,根據(jù)父進(jìn)程內(nèi)存快照生成臨時(shí)rdb文件,完成后對(duì)原有文件進(jìn)行替換。
- 子進(jìn)程發(fā)送信號(hào)給父進(jìn)程表示完成,父進(jìn)程更新統(tǒng)計(jì)信息,可通過info命令查看Persistence信息。
-
兩個(gè)要點(diǎn):fork and cow (copy on write)
- fork 這個(gè)過程不是拷貝父進(jìn)程的物理內(nèi)存空間,而是拷貝父進(jìn)程父進(jìn)程內(nèi)存空間頁表(記錄物理內(nèi)存空間地址),父子進(jìn)程共享物理內(nèi)存空間,此過程會(huì)消耗時(shí)間,造成阻塞,數(shù)據(jù)量很大時(shí),對(duì)性能會(huì)造成影響。
- copy on write fork出子進(jìn)程后,父進(jìn)程繼續(xù)處理請(qǐng)求,子進(jìn)程負(fù)責(zé)將內(nèi)存數(shù)據(jù)寫入臨時(shí)文件。不需要完全拷貝出父進(jìn)程內(nèi)存,因?yàn)閘inux有寫時(shí)復(fù)制(copy on write)機(jī)制。父進(jìn)程在處理寫請(qǐng)求時(shí),會(huì)把要修改的內(nèi)存頁創(chuàng)建副本,而不是修改共享的內(nèi)存頁。子進(jìn)程的地址空間內(nèi)數(shù)據(jù),是fork時(shí)刻數(shù)據(jù)庫的快照。
.rdb文件默認(rèn)開啟壓縮,采用LZF算法,雖然消耗一定性能,不過可以大幅降低文件體積,方便保存到硬盤或通過網(wǎng)絡(luò)發(fā)送給從節(jié)點(diǎn)。
config set rdbcompression yes|no
三、AOF
開啟AOF
- 配置文件設(shè)置 appendonly yes | no , 默認(rèn)不開啟。
AOF文件同步
- 命令寫入時(shí),會(huì)先寫入aof_buf緩存中,然后同步到磁盤,同步模式有三種:
appendfsync always // 通過系統(tǒng)調(diào)用fsync, 每次收到寫命令就立即強(qiáng)制寫入磁盤,最慢的,但是保證完全的持久化,不推薦使用
appendfsync everysec // 通過系統(tǒng)調(diào)用write,每秒鐘強(qiáng)制寫入磁盤一次,在性能和持久化方面做了很好的折中,默認(rèn)。
appendfsync no // write操作,完全依賴os,性能最好,持久化沒保證,通常不會(huì)超過30s。
- 系統(tǒng)調(diào)用fsync和write
- fsync,在操作文件時(shí),強(qiáng)制將高速緩存中的內(nèi)容同步到硬盤。
- write,在調(diào)用后,數(shù)據(jù)寫入高速緩沖區(qū),此時(shí),系統(tǒng)調(diào)用立刻返回。同步硬盤操作依賴于系統(tǒng)調(diào)度。如果此時(shí)發(fā)生宕機(jī),緩存區(qū)數(shù)據(jù)會(huì)丟失。
- .aof文件以直接文本協(xié)議格式保存。
AOF重寫機(jī)制
- 隨著命令的不斷寫入,.aof文件越來越大,redis通過重寫機(jī)制壓縮.aof文件體積,觸發(fā)時(shí)機(jī)由auto-aof-rewrite-min-size和auto-aof-rewrite-percentage參 數(shù)確定。此外,redis提供了命令bgrewriteaof手動(dòng)觸發(fā)重寫機(jī)制。
- 重寫的過程如下:
- redis執(zhí)行AOF重寫,如果當(dāng)前正在進(jìn)行aof重寫,則不執(zhí)行,返回正在進(jìn)行中的錯(cuò)誤響應(yīng)。如果當(dāng)前正在進(jìn)行bgsave,重寫命令延遲到bgsave執(zhí)行完畢進(jìn)行。
- 父進(jìn)程進(jìn)行fork創(chuàng)建子進(jìn)程,開銷等于bgsave過程。
- 父進(jìn)程繼續(xù)響應(yīng)請(qǐng)求,將新的數(shù)據(jù)保存到AOF重寫緩沖區(qū),由子進(jìn)程操作共享內(nèi)存,(同樣基于copy on write技術(shù))。
- 子進(jìn)程根據(jù)內(nèi)存快照,按照合并規(guī)則寫入到新的AOF文件。
- 子進(jìn)程發(fā)送信號(hào)給父進(jìn)程表示完成,父進(jìn)程更新統(tǒng)計(jì)信息,可通過info命令查看Persistence信息。
- 父進(jìn)程把AOF緩沖區(qū)文件寫入到新的AOF文件。
- 用新的AOF文件替換老的AOF文件。
- 可以通過no-appendfsync-on-rewrite,決定是否在重寫期間進(jìn)行磁盤同步,默認(rèn)不開啟,因?yàn)楸旧碇貙憣?duì)磁盤IO開銷比較大,不過在這可能會(huì)造成重寫期間的數(shù)據(jù)丟失。
AOF阻塞
- 對(duì)于采用everysec的配置,AOF線程負(fù)責(zé)刷盤同步,1s一次。不過redis采取延遲fsync策略,當(dāng)一次同步超過1s時(shí),會(huì)在再等待1s。每次同步前,主線程都會(huì)檢測(cè)上次同步成功時(shí)間,如果距離上次同步時(shí)間超過2s,主線程會(huì)進(jìn)入阻塞狀態(tài),直到同步完成。
- 極端情況下,AOF最多丟失2s內(nèi)的數(shù)據(jù)。
- 每當(dāng)發(fā)生AOF阻塞,aof_delayed_fsync都會(huì)累加,可以通過這個(gè)指標(biāo)查看AOF阻塞問題,主要通過優(yōu)化磁盤負(fù)載解決。
redis重啟加載
- AOF持久化開啟,并且.aof文件存在,優(yōu)先加載.aof文件,否則不進(jìn)行AOF恢復(fù)。
- RDB持久化開啟,并且.rdb文件存在,根據(jù).rdb文件進(jìn)行恢復(fù)。
- 加載.aof和.rdb文件時(shí),都會(huì)進(jìn)行文件校驗(yàn)。文件損壞時(shí),會(huì)拒絕啟動(dòng)。對(duì)于rdb可以用Redis的redis-check-dump文件進(jìn)行檢測(cè)。對(duì)于.aof文件,可以通過redis-check-aof --fix進(jìn)行恢復(fù)。