Redis-AOF持久化

RDBAOF 區別在於: 前者保存數據庫快照,持久化全部鍵值對,後者經過保存 寫命令 保證數據庫的狀態.mysql

什麼是 AOF ?

AOF 持久化經過保存服務器執行的寫命令實現,進行恢復時經過重放 AOF 文件中的寫命令,來保證數據安全.就像 mysqlbinlog 同樣.git

開啓 AOF

經過在 redis.conf 中將 appendonly 設爲 yes 便可github

# redis.conf
appendonly yes
# 設置 aof 文件名字
appendfilename "appendonly.aof"
# Redis支持三種不一樣的刷寫模式:
# appendfsync always #每次收到寫命令就當即強制寫入磁盤,是最有保證的徹底的持久化,但速度也是最慢的,通常不推薦使用。
appendfsync everysec #每秒鐘強制寫入磁盤一次,在性能和持久化方面作了很好的折中,是受推薦的方式。
# appendfsync no #徹底依賴OS的寫入,通常爲30秒左右一次,性能最好可是持久化最沒有保證,不被推薦。
複製代碼

AOF 文件格式

AOF 文件格式以 redis 命令請求協議爲標準的,*.aof 文件能夠直接打開.redis

redis設計與實現-aof格式

AOF 持久化過程

命令追加 append

redis 執行完客戶端的寫命令後,會將該命令以協議的格式寫入到 aof_buf 中.該屬性爲 redisServer 中的一個.sql

#src/server.h
struct redisServer {
 ....
 sds aof_buf;      /* AOF buffer, written before entering the event loop */
}
複製代碼

AOF 寫入同步

redis 的服務進程是一個 事件循環 - event loop , 每次循環大概會作三件事.數據庫

  1. 文件事件: 接收客戶端的命令,返回結果
  2. 時間事件: 執行系統的定時任務(serverCron), 完成漸進 rehash 擴容之類的操做
  3. aof flush: 是否將 aof_buf 中的內容寫入文件中
# 僞代碼
def eventloop():
 while true:
 	processFileEvents() # 處理命令
 	processTimeEvents() # 處理定時任務
 	flushAppendOnlyFile() # 處理 aof 寫入
 	
複製代碼

flushAppendOnlyFile 中的動做是否執行是根據一個配置決定的.緩存

appendfsync

該配置有幾個值可選,默認是 everysec.安全

  1. always: 老是寫入.只要程序執行到這一步了,就將 aof_buf 中命令協議寫入到文件
  2. everysec: 每秒寫入. 每次執行前會先判斷是否與上次寫入間隔一秒,再次同步時經過 一個線程 專門執行
  3. no: 不寫入. 命令寫入 aof_buf 後由操做系統決定什麼時候同步到文件

fsync: 現代操做系統爲了提升文件讀寫的效率,一般會將 write 函數寫入的數據緩存在內存中,等到緩存空間填滿或者超過必定時限,再將其寫入磁盤.這樣的問題在於宕機時緩存中的數據就沒法恢復.因此操做系統提供了 fsync/fdatasync 兩個函數,強制操做系統將數據當即寫入磁盤,保證數據安全.兩函數區別在於: 前者會更新文件的屬性,後者只更新數據.bash

三種模式在性能和數據上都有相對的優缺點. always 模式數據安全性更強,畢竟每次都是直接寫入,可是就會影響性能.磁盤讀寫是比較慢的. everysec 模式性能較好,但會丟失一秒內的緩存數據. no 模式就徹底取決於操做系統了.服務器

AOF 還原數據

redis設計與實現-aof還原數據

AOF 重寫

AOF 重寫的意思其實就是對單個命令的多個操做進行整理,留下最終態的執行命令來減小 aof 文件的大小.你能夠想象一下執行 1w 次 incr 操做,寫入 aof 1w 次的場景.

觸發條件

AOF 重寫能夠自動觸發.經過配置 auto-aof-rewrite-min-sizeauto-aof-rewrite-percentage,知足條件就會自動重寫.具體能夠查看官方的 redis.conf

重寫過程

  1. 建立子進程,根據內存裏的數據重寫aof,保存到temp文件
  2. 此時主進程還會接收命令,會將寫操做追加到舊的aof文件中,並保存在server.aof_rewrite_buf_blocks中,經過管道發送給子進程存在server.aof_child_diff中,最後追加到temp文件結尾
  3. 子進程重寫完成後退出,主進程根據子進程退出狀態,判斷成功與否。成功就將剩餘的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 操做是原子的,也是惟一會形成主進程阻塞的操做.

參考

  1. redis.io/topics/pers…
  2. youjiali1995.github.io/redis/persi…
相關文章
相關標籤/搜索