Redis 支持RDB和AOF兩種持久化機(jī)制,之所以存在兩種,是因為它們各自適用于不同的場景、不同的階段。我接下來對其進(jìn)行介紹,并分析我們在實(shí)際場景中如何使用配置。
RDB
有兩個重要命令,save和bgsave,一個是同步,一個是異步,完成后會在指定的目錄生成一份壓縮文件(默認(rèn)是dump.rdb,使用LZF算法,可以通過dbfilename配置,dir配置文件夾)。
- save: 阻塞當(dāng)前Redis服務(wù)器、直到RDB過程完成,因為會阻塞線程,所以基本被廢棄了。
- bgsave: Redis主線程會進(jìn)行fork操作,創(chuàng)建子進(jìn)程,RDB持久化過程由子進(jìn)程負(fù)責(zé),雖然也會有阻塞,但只阻塞fork階段,這個命令是對save的一個改進(jìn)
- 自動保存,在程序中以下情景會自動觸發(fā)bgsave
- 使用save相關(guān)配置,如
"save m n",表示m秒內(nèi)數(shù)據(jù)存在n次修改時自動觸發(fā),可以配置多個規(guī)則 - 如果從節(jié)點(diǎn)執(zhí)行全量復(fù)制,那么master節(jié)點(diǎn)會自動執(zhí)行bgsave,然后將RDB文件發(fā)給從節(jié)點(diǎn)
- 執(zhí)行debug reload 命令重新加載Redis時,也會觸發(fā)
- 在shutdown命令執(zhí)行后,如果沒有開啟AOF持久化功能,會觸發(fā)bgsave
- 使用save相關(guān)配置,如
優(yōu)勢:
- 是一個壓縮后的二進(jìn)制文件,代表某個時間點(diǎn)的快照,特別適合發(fā)送到其他節(jié)點(diǎn)。
- Redis加載RDB的速度遠(yuǎn)遠(yuǎn)快于AOF
缺陷
- 沒辦法實(shí)時的持久化,bgsave是一個重量級的操作,不可能頻繁執(zhí)行
- RDB文件使用特定格式保存
AOF
為了應(yīng)對RDB的缺點(diǎn),AOF方式產(chǎn)生。以獨(dú)立日志的方式記錄每次命令,重啟的時候再重新執(zhí)行AOF文件中的命令達(dá)到恢復(fù)數(shù)據(jù)的目的。
開啟
默認(rèn)是不開啟的,需要配置 appendonly yes,默認(rèn)文件名是appendonly.aof,路徑與RDB一致。-
工作流程
- 將寫入命令追加到aof_buf緩沖區(qū)中
- AOF緩沖區(qū)根據(jù)對應(yīng)的策略向硬盤做同步工作fsync
- 隨著AOF文件越來越大,需要定期重寫,達(dá)到壓縮的目的
- 當(dāng)redis重啟時,可以加載AOF文件進(jìn)行數(shù)據(jù)恢復(fù)
文件格式
為文本協(xié)議格式,也就是之前講過的通信協(xié)議的格式,如:·*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n
之所以采用文本協(xié)議,是因為其兼容性好,而且可讀性比較強(qiáng),可以直接修改-
文件同步: appendfsync配置
- always 寫入aof_buf后立即同步到文件,fsync完成后線程返回
- everysec 建議的配置,命令寫入aof_buf后調(diào)用系統(tǒng)write操作,完成后線程返回。fsync同步文件操作,由另一個線程每秒調(diào)用一次。
- no 寫入aof_buf后調(diào)用系統(tǒng)write操作,不對AOF文件做fsync同步,同步的步驟由系統(tǒng)來做,最長30s
- write:利用頁緩沖區(qū)來提高硬盤IO性能,會有短暫的延遲,如果真正同步之前發(fā)生宕機(jī),則會丟失數(shù)據(jù)。因此系統(tǒng)同時提供了fsync、fdatasync等同步函數(shù),可以強(qiáng)制操作系統(tǒng)立刻將緩沖區(qū)中的數(shù)據(jù)寫入到硬盤里,從而確保數(shù)據(jù)的安全性
- fsync:針對單個文件操作(比如AOF文件),做強(qiáng)制硬盤同步,fsync將阻塞直到寫入硬盤后返回。
-
重寫機(jī)制,重寫采用了以下方法實(shí)現(xiàn)了壓縮
- 進(jìn)程內(nèi)超時的數(shù)據(jù)不再寫入
- 無效命令不再寫入(也就是中間過程)
- 合并多條命令,比如lpush list a,lpush list b -> lpush list a b c.
- 手動觸發(fā): bgrewriteaof
- 自動觸發(fā): auto-aof-rewrite-min-size和auto-aof-rewrite-percentage
- 重寫過程: 主進(jìn)程fork一個新進(jìn)程,并使用AOF重寫緩沖區(qū)保存重寫期間的數(shù)據(jù)。重寫完成后,父進(jìn)程吧重寫緩沖區(qū)的數(shù)據(jù)刷新到新的文件。
重啟加載
記住,優(yōu)先加載AOF

運(yùn)維優(yōu)化
-
fork操作
fork操作是一個重量級操作,子進(jìn)程會復(fù)制父進(jìn)程的空間內(nèi)存頁表,在搞ops情況下有可能阻塞大量的命令。- 優(yōu)先使用物理機(jī),或者高效的虛擬化技術(shù)
- 控制Redis實(shí)例最大可用內(nèi)存,耗時時間跟內(nèi)存(內(nèi)存頁)成正比
- 合理配置Linux內(nèi)存分配
- 降低fork的頻率,也就是放款A(yù)OF自動觸發(fā)的機(jī)制
-
子進(jìn)程
- cpu 在子進(jìn)程將進(jìn)程中的文件分批寫入的時候消耗比較大
- Redis是密集型服務(wù),所以不要做單核綁定(子進(jìn)程會搶占),可以使用多實(shí)例部署的方式
- 內(nèi)存,子進(jìn)程共享父進(jìn)程的內(nèi)存快照,在新命令時,父進(jìn)程會創(chuàng)建內(nèi)存頁副本,這一部分是增加的內(nèi)存(AOF還有重寫緩沖區(qū))。
- 因此對于內(nèi)存,盡量保證只有一個子進(jìn)程,另外不要再大量寫入時觸發(fā)重寫操作。
AOF阻塞
在子線程同步磁盤時,主線程會不斷對比上次AOF同步時間,如果超過2S(everysec方式),則會阻塞等待。如果發(fā)生阻塞,很可能是磁盤IO存在高負(fù)荷,導(dǎo)致同步變慢。