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

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