1. 引子
redis所有數(shù)據(jù)保存在內存中,為防止數(shù)據(jù)丟失,redis通過對數(shù)據(jù)的更新異步地保存到磁盤中來實現(xiàn)持久化。為實現(xiàn)持久化,redis有兩種方式可供選擇:RDB和AOF。
RDB:快照形式,保存某一時刻的所有內存數(shù)據(jù)到磁盤中的二進制文件中。
AOF:將執(zhí)行過的命令保存到日志中,恢復數(shù)據(jù)就是重新執(zhí)行一遍日志中命令的過程。
2. RDB
RDB存儲觸發(fā)機制分為手動觸發(fā)和自動觸發(fā)兩類。
2.1 手動觸發(fā)
2.1.1 save命令
- 客戶端執(zhí)行save命令后將會創(chuàng)建一個RDB文件。在執(zhí)行save時會進行同步阻塞,如果耗時較長時,其他客戶端再執(zhí)行其他命令就會發(fā)生等待。
- 如果本次save操作時已有存在的舊的RDB文件,那么本次save操作將會生成一個新的臨時的RDB文件,等到save執(zhí)行完后,將這個新的RDB文件替換舊的RDB文件。
- 線上由于數(shù)據(jù)量大,使用save命令由于阻塞比較危險,已經廢棄該操作。
2.1.2 bgsave命令
- 客戶端執(zhí)行bgsave命令時,當前redis進程將會fork出一個子進程,并在子進程中進行創(chuàng)建和保存RBD文件的過程。當子進程保存完后,返回"bgsave successfully"結果給主進程。使用bgsave除了在fork子進程的時候會阻塞(很短暫的時間),其他步驟不會進行阻塞。
2.2 自動觸發(fā)
- redis內部設置了自動執(zhí)行bgsave命令的配置文件,如可以設置60秒內發(fā)生了10000次寫操作就可以觸發(fā)一次RBD文件的生成。
- 如果具備主從復制結構,從節(jié)點執(zhí)行全量復制操作時,主節(jié)點會自動執(zhí)行bgsave命令生成RDB文件并發(fā)送給從節(jié)點。
- 執(zhí)行debug reload命令重新加載redis時也會自動執(zhí)行bgsave。
- 默認情況下執(zhí)行shutdown命令時,如果沒有開啟AOF持久化功能也會自動執(zhí)行bgsave。
配置文件conf:
- dir:RDB文件的存儲目錄
- dbfilename:RDB文件的文件名
- Save 60 10000 // 60秒內執(zhí)行了10000次寫操作就觸發(fā)RDB的自動生成
3. AOF
由于RBD具有耗時耗性能,不可控和丟失數(shù)據(jù)等問題,引出了另一種持久化方式AOF。AOF以日志的形式來保存了每次的寫操作,重啟時只要再執(zhí)行一遍AOF文件中的所有寫命令就可以達到恢復數(shù)據(jù)的目的。AOF是redis主流的持久化技術。
AOF有三種寫入策略:always,everysec,no。
3.1 AOF工作流程

從圖中可以看到AOF寫入時并不是直接將命令寫入到磁盤文件中,而是先寫入到緩沖區(qū)中(因為磁盤寫入速度慢,內存寫入速度快),然后通過不同的寫入策略將內存的數(shù)據(jù)同步到文件中。
3.2 AOF寫入策略
Always: 每執(zhí)行一次寫入命令就會同步將緩沖區(qū)中的數(shù)據(jù)同步到文件中。這種策略的問題就是IO開銷較大,不建議使用。
Everysec:每秒一次同步緩沖區(qū)中的數(shù)據(jù)到文件中。問題是可能會丟失1秒的數(shù)據(jù)。是建議的同步策略
No:由操作系統(tǒng)來確定何時同步,使用者不用管。由于存在安全性的問題,不建議使用。
3.3 重寫機制
隨著命令不斷寫入會導致文件越來越大,為了解決這個問題,redis實現(xiàn)了AOF重寫機制壓縮文件體積。
重寫機制會對如下幾種情況進行優(yōu)化:
- 過期的數(shù)據(jù)(如設置了過期時間,超期后沒有用的)
- 列表等分多次插入的命令合并為一條名稱一次性插入
- 后面的命令的值對前面的命令的值覆蓋的情況,如果set hello world;set hello java;實際只需要保存最后一次命令就行。
通過重寫機制,可以減少磁盤占用量,加速恢復速度。
同樣的,AOF重寫可以分為手動觸發(fā)和自動觸發(fā)兩種方式。
- 手動觸發(fā):執(zhí)行bgrewriteaof命令,創(chuàng)建一個子進程來執(zhí)行重寫過程。
- 自動觸發(fā):AOF重寫配置,conf文件中,auto-of-rewrite-min-size表示AOF文件重寫需要的尺寸;auto-of-rewrite-percentage表示AOF文件增長率。
使用AOF時,conf相關配置如下:
appendonly yes // 啟動AOF持久化
appendfilename "xxx.aof" // 指定文件名
appenfsync everysec // 重寫策略,每秒執(zhí)行一次
dir // 保存日志的目錄
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
加上重寫機制后,AOF寫入流程如下:

要注意的是為保證子進程針對原緩沖區(qū)進行重寫過程中客戶端新寫入的命令不丟失,redis單獨創(chuàng)建了另外一塊緩沖區(qū),等到重寫結束后再將這個單獨的緩沖區(qū)的數(shù)據(jù)寫入到AOF文件中。