RDB
和 AOF
區別在於: 前者保存數據庫快照,持久化全部鍵值對,後者經過保存 寫命令 保證數據庫的狀態.mysql
AOF
持久化經過保存服務器執行的寫命令實現,進行恢復時經過重放 AOF
文件中的寫命令,來保證數據安全.就像 mysql
的 binlog
同樣.git
經過在 redis.conf
中將 appendonly
設爲 yes
便可github
# redis.conf
appendonly yes
# 設置 aof 文件名字
appendfilename "appendonly.aof"
# Redis支持三種不一樣的刷寫模式:
# appendfsync always #每次收到寫命令就當即強制寫入磁盤,是最有保證的徹底的持久化,但速度也是最慢的,通常不推薦使用。
appendfsync everysec #每秒鐘強制寫入磁盤一次,在性能和持久化方面作了很好的折中,是受推薦的方式。
# appendfsync no #徹底依賴OS的寫入,通常爲30秒左右一次,性能最好可是持久化最沒有保證,不被推薦。
複製代碼
AOF
文件格式以 redis
命令請求協議爲標準的,*.aof
文件能夠直接打開.redis
redis
執行完客戶端的寫命令後,會將該命令以協議的格式寫入到 aof_buf
中.該屬性爲 redisServer
中的一個.sql
#src/server.h
struct redisServer {
....
sds aof_buf; /* AOF buffer, written before entering the event loop */
}
複製代碼
redis
的服務進程是一個 事件循環 - event loop
, 每次循環大概會作三件事.數據庫
serverCron
), 完成漸進 rehash
擴容之類的操做aof_buf
中的內容寫入文件中# 僞代碼
def eventloop():
while true:
processFileEvents() # 處理命令
processTimeEvents() # 處理定時任務
flushAppendOnlyFile() # 處理 aof 寫入
複製代碼
flushAppendOnlyFile
中的動做是否執行是根據一個配置決定的.緩存
該配置有幾個值可選,默認是 everysec
.安全
aof_buf
中命令協議寫入到文件aof_buf
後由操做系統決定什麼時候同步到文件fsync: 現代操做系統爲了提升文件讀寫的效率,一般會將
write
函數寫入的數據緩存在內存中,等到緩存空間填滿或者超過必定時限,再將其寫入磁盤.這樣的問題在於宕機時緩存中的數據就沒法恢復.因此操做系統提供了 fsync/fdatasync 兩個函數,強制操做系統將數據當即寫入磁盤,保證數據安全.兩函數區別在於: 前者會更新文件的屬性,後者只更新數據.bash
三種模式在性能和數據上都有相對的優缺點. always
模式數據安全性更強,畢竟每次都是直接寫入,可是就會影響性能.磁盤讀寫是比較慢的. everysec
模式性能較好,但會丟失一秒內的緩存數據. no
模式就徹底取決於操做系統了.服務器
AOF
重寫的意思其實就是對單個命令的多個操做進行整理,留下最終態的執行命令來減小 aof
文件的大小.你能夠想象一下執行 1w 次 incr
操做,寫入 aof
1w 次的場景.
AOF
重寫能夠自動觸發.經過配置 auto-aof-rewrite-min-size
和auto-aof-rewrite-percentage
,知足條件就會自動重寫.具體能夠查看官方的 redis.conf
aof
,保存到temp
文件aof
文件中,並保存在server.aof_rewrite_buf_blocks
中,經過管道發送給子進程存在server.aof_child_diff
中,最後追加到temp
文件結尾server.aof_rewrite_buf_blocks
追加到temp file
中,而後rename()
覆蓋原aof
文件重寫的過程當中主進程仍是會一直接受客戶端的命令,因此重寫子進程與主進程確定會存在數據不一致的狀況.redis
針對這種狀況做出瞭解決方案: 新增一個 aof_rewrite_buf_blocks
, aof
寫入命令時,不只寫入到 aof_buf
, 若是正在重寫,那麼也寫入到 aof_rewrite_buf_blocks
中,這樣在子進程重寫完畢後,能夠將 aof_rewrite_buf_blocks
的命令追加到新文件中,保證數據不丟失.
rename
操做是原子的,也是惟一會形成主進程阻塞的操做.