04 AOF日誌:宕機了,Redis如何避免數據丟失

接下來兩篇將記錄Redis持久化存儲兩大技術:AOF日誌、RDB快照

本篇重點

“AOF日誌實現”
“AOF日誌三種寫回策略”
“AOF重寫——避免日誌過大的解決方案”

前言

Redis持久化存儲兩大技術:AOF日誌、RDB快照

AOF: Append Only File
RDB: Redis DB

背景

Redis運行中,若突然宕機,存儲在內存中的數據都會丟失。此時如果從後端數據庫恢復數據,雖然可行,但也會導致效率問題:

  • 頻繁訪問數據庫增加數據庫壓力
  • 慢速數據庫讀取導致Redis性能下降

因此,Redis實現數據持久化的方式,要避免從後端數據庫中恢復數據,採用的方式就是AOF日誌和RDB快照,本篇文章主要討論AOF日誌。

1. AOF日誌實現

  • 寫後日志:先執行命令,數據寫入內存;再記錄日誌
  • 日誌記錄內容:Redis收到的每一條命令,記錄格式如下:
    • "*+number"——當前命令有number個字段,後面內容是對應字段描述

    • "$+number"——表示當前字段佔用的字節數,後面跟具體字段名稱

    • 例子:命令:set testkey testvalue,寫入AOF日誌後的格式是

      *3          // 當前命令3個字段(分別是set testkey testvalue)
      $3          // 第一個字段佔3B
      set         // 第一個字段名:set
      $7
      testkey
      $9
      testvalue
      
  • “寫後日志”的原因
    • Redis記錄AOF日誌時不會對命令進行語法檢查(節省檢查開銷)
    • 基於第一點,採用“寫後日志”防止記錄錯誤命令
  • AOF日誌在主線程中執行
  • AOF不會阻塞當前寫操作(先執行命令,後記錄日誌)
  • AOF潛在風險:
    • AOF存在阻塞下一個操作的風險(下個操作執行之前主線程寫上一個操作的日誌)
    • 若Redis直接用作數據庫,命令執行後系統宕機——AOF日誌沒記錄導致數據丟失

以上的AOF潛在風險都與AOF日誌寫盤時間相關,解決方案——AOF三種寫回策略

2. AOF日誌三種寫回策略——appendfsync參數的三個可選項

Always——同步寫回:每個寫命令執行後,同步寫磁盤

Everysec——每秒寫回:日誌暫時寫到AOF日誌cache,每隔1s寫盤

No——操作系統控制的寫回:日誌暫時寫到AOF日誌cache,由OS決定何時寫盤

配置項 寫回時機 優點 缺點 適用場景
Always 同步寫回 可靠性高
數據基本不丟失
每個寫操作都伴隨寫盤,性能影響較大 高可靠性
Everysec 每秒寫回 性能適中 宕機時丟失1s內數據 允許少量數據丟失,同時性能影響較小
No OS控制寫回 性能好 宕機時丟失數據較多 高性能

QA

Q: AOF文件過大帶來的一系列性能問題?如何控制AOF文件過大?

A: 性能問題

  • 文件系統本身文件大小的限制
  • 文件太大時,追加命令記錄效率變低
  • 宕機後,AOF文件中的命令挨個重新執行的導致的故障恢復過程緩慢

解決方案:AOF重寫機制

3. AOF重寫——避免AOF日誌過大

  • AOF重寫:Redis根據數據庫現狀,創建一個新的AOF文件
  • 原理:“多變一”——某個KV被多條命令反覆修改
  • AOF重寫是否會阻塞主線程?AOF重寫機制。
    • AOF日誌由主線程寫盤
    • AOF重寫日誌由後臺子進程bgrewriteaof執行
  • 重寫過程——“一個拷貝,兩處日誌”
    • “一個拷貝”:主線程fork bgrewriteaof子進程,通過拷貝頁表(OS的“寫時複製”原則)訪問主線程的內存數據
    • “兩處日誌”:寫操作發生時,AOF日誌與AOF重寫均先將操作記錄到各自日誌cache中,隨後fork bgrewriteaof子進程進程重寫日誌操作
  • AOF非阻塞的重寫過程

    AOF非阻塞的重寫過程

結尾

AOF故障恢復需要運行所有操作記錄,即“重放”過程很慢,既能避免數據丟失,又能更快恢復數據的方法——“RDB快照”

圖片來源於極客時間專欄《Redis核心技術與實戰》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章