目录
一、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 就像银行 “既实时记流水,又定期给流水瘦身” 的策略 —— 既保证交易可追溯,又避免流水册无限膨胀。