目錄
一、AOF 的核心邏輯:“每筆交易都記流水”
二、AOF 的三個步驟:從 “臨時記錄” 到 “正式歸檔”
1. 命令追加:記到 “臨時小本本”
2. 寫入與同步:抄到 “正式流水冊”
3. AOF 還原:拿 “流水冊” 重放交易
三、AOF 重寫:給 “流水冊” 瘦身(解決文件膨脹)
重寫邏輯:派 “實習生(子進程)” 寫 “精簡流水冊”
四、銜接之前的結構知識
如果把 Redis 比作銀行的核心交易系統(處理存款、取款、轉賬等 “寫操作”),那么 AOF 持久化就像銀行的 “交易流水單”—— 通過記錄 “每一筆交易命令”,確保系統故障后能還原所有賬戶的最終狀態。
一、AOF 的核心邏輯:“每筆交易都記流水”
與 RDB“定期拍紙質賬本快照(全量備份)” 不同,AOF 是 “實時記錄交易命令(增量備份)”:
- RDB 像 “每月拍一次金庫賬本的照片”;
- AOF 像 “每筆交易都記在流水單上”。
二、AOF 的三個步驟:從 “臨時記錄” 到 “正式歸檔”
1. 命令追加:記到 “臨時小本本”
struct redisServer {// ...// AOF緩沖區,每次追加到 aof_buf 末尾sds aof_buf;// ...
};
銀行柜員每完成一筆交易(如 “給用戶 A 存 100 元”,對應 Redis 的SET user:A 100
命令),會立刻把交易內容按固定格式(Redis 協議)寫進 “臨時小本本”(aof_buf
緩沖區)。
- ?類比:Redis 執行完寫命令后,把命令丟進
aof_buf
臨時存著,等后續統一歸檔。
2. 寫入與同步:抄到 “正式流水冊”
銀行有個 “歸檔員”(flushAppendOnlyFile
函數),負責把 “臨時小本本” 的內容抄到 “正式流水冊(AOF 文件)”。抄的嚴格程度由appendfsync
選項決定,對應三種策略:
appendfsync 選項 | 銀行場景類比(歸檔規則) | 技術特點 |
---|---|---|
always | 每筆交易后,立刻抄到流水冊并強制存進保險箱 | 最安全(最多丟 1 筆交易),但最慢(柜員總在等歸檔) |
everysec | 每秒抄一次流水冊,用小助手(子線程)每秒強制存保險箱 | 平衡安全與性能(最多丟 1 秒交易),Redis 默認選擇 |
no | 只抄到流水冊,啥時候存保險箱交給銀行后臺(操作系統) | 最快,但最不安全(后臺可能延遲很久存,停電丟多筆) |
3. AOF 還原:拿 “流水冊” 重放交易
如果銀行核心系統故障,要恢復數據,就把 “正式流水冊(AOF 文件)” 里的交易,從頭到尾再做一遍:
-
銀行找個 “模擬柜員”(偽客戶端,無網絡連接但能執行命令),照著流水冊的記錄,重新執行每一筆交易(如 “給用戶 A 存 100 元”“給用戶 B 轉 50 元”),最終還原所有賬戶的余額。
三、AOF 重寫:給 “流水冊” 瘦身(解決文件膨脹)
問題:流水冊會越來越厚
比如反復操作同一個賬戶:
RPUSH list "A" "B" # list變成["A","B"]
RPUSH list "C" # list變成["A","B","C"]
LPOP list # list變成["B","C"]
RPUSH list "D" "E" # list變成["B","C","D","E"]
流水冊里會記 4 條命令,但最終 list 是["B","C","D","E"]
-
顯然,用? 一條
RPUSH list "B" "C" "D" "E"
?就能代替這 4 條,卻能達到同樣效果。
重寫邏輯:派 “實習生(子進程)” 寫 “精簡流水冊”
為了讓流水冊變薄,銀行會做 “流水冊重寫”:
-
派實習生(子進程):子進程先看當前所有賬戶的最終狀態(比如直接查 list 的最終元素是
["B","C","D","E"]
)。 -
生成最簡命令:用一條
RPUSH list "B" "C" "D" "E"
代替原來的 4 條命令,寫一本 “精簡流水冊”。 -
處理重寫期間的新交易:重寫時,新交易(如
RPUSH list "F"
)會同時記到 “原來的流水冊” 和 “重寫小緩沖區”。 -
最終替換:實習生寫完 “精簡流水冊” 后,銀行把 “重寫小緩沖區” 里的新交易(
RPUSH list "F"
)追加到新流水冊末尾,然后用新流水冊替換舊的 —— 這樣新流水冊既包含所有最終狀態,又沒有冗余命令。
四、銜接之前的結構知識
-
與 RDB 互補:RDB 是 “定期全量備份(像每月拍賬本照片)”,恢復快但實時性差;AOF 是 “增量交易記錄(像流水單)”,實時性好但恢復慢、文件易膨脹。Redis 通常結合兩者:用 RDB 做基礎全量備份,用 AOF 做增量補充,保障數據安全。
-
與內存對象關聯:AOF 記錄的 “寫命令”,操作的是 Redis 內存中的字符串、列表、哈希等對象;重寫時,子進程直接讀取內存中對象的最終狀態(如列表的最終元素),再生成最簡命令,避免解析舊 AOF 的冗余命令。
這樣,AOF 就像銀行 “既實時記流水,又定期給流水瘦身” 的策略 —— 既保證交易可追溯,又避免流水冊無限膨脹。