Redis AOF 持久化:银行的 “交易流水单” 管理逻辑

目录

[一、AOF 的核心逻辑:"每笔交易都记流水"](#一、AOF 的核心逻辑:“每笔交易都记流水”)

[二、AOF 的三个步骤:从 "临时记录" 到 "正式归档"](#二、AOF 的三个步骤:从 “临时记录” 到 “正式归档”)

[1. 命令追加:记到 "临时小本本"](#1. 命令追加:记到 “临时小本本”)

[2. 写入与同步:抄到 "正式流水册"](#2. 写入与同步:抄到 “正式流水册”)

[3. AOF 还原:拿 "流水册" 重放交易](#3. AOF 还原:拿 “流水册” 重放交易)

[三、AOF 重写:给 "流水册" 瘦身(解决文件膨胀)](#三、AOF 重写:给 “流水册” 瘦身(解决文件膨胀))

[重写逻辑:派 "实习生(子进程)" 写 "精简流水册"](#重写逻辑:派 “实习生(子进程)” 写 “精简流水册”)

四、衔接之前的结构知识


如果把 Redis 比作银行的核心交易系统(处理存款、取款、转账等 "写操作"),那么 AOF 持久化就像银行的 "交易流水单"------ 通过记录 "每一笔交易命令",确保系统故障后能还原所有账户的最终状态。

一、AOF 的核心逻辑:"每笔交易都记流水"

与 RDB"定期拍纸质账本快照(全量备份)" 不同,AOF 是 "实时记录交易命令(增量备份)":

  • RDB 像 "每月拍一次金库账本的照片";
  • AOF 像 "每笔交易都记在流水单上"。

二、AOF 的三个步骤:从 "临时记录" 到 "正式归档"

1. 命令追加:记到 "临时小本本"

cpp 复制代码
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 条,却能达到同样效果。

重写逻辑:派 "实习生(子进程)" 写 "精简流水册"

为了让流水册变薄,银行会做 "流水册重写":

  1. 派实习生(子进程) :子进程先看当前所有账户的最终状态 (比如直接查 list 的最终元素是["B","C","D","E"])。

  2. 生成最简命令 :用一条RPUSH list "B" "C" "D" "E"代替原来的 4 条命令,写一本 "精简流水册"。

  3. 处理重写期间的新交易 :重写时,新交易(如RPUSH list "F")会同时记到 "原来的流水册" 和 "重写小缓冲区"。

  4. 最终替换 :实习生写完 "精简流水册" 后,银行把 "重写小缓冲区" 里的新交易(RPUSH list "F")追加到新流水册末尾,然后用新流水册替换旧的 ------ 这样新流水册既包含所有最终状态,又没有冗余命令。

四、衔接之前的结构知识

  • 与 RDB 互补 :RDB 是 "定期全量备份(像每月拍账本照片)",恢复快但实时性差;AOF 是 "增量交易记录(像流水单)",实时性好但恢复慢、文件易膨胀。Redis 通常结合两者:用 RDB 做基础全量备份,用 AOF 做增量补充,保障数据安全。

  • 与内存对象关联 :AOF 记录的 "写命令",操作的是 Redis 内存中的字符串、列表、哈希等对象;重写时,子进程直接读取内存中对象的最终状态(如列表的最终元素),再生成最简命令,避免解析旧 AOF 的冗余命令。

这样,AOF 就像银行 "既实时记流水,又定期给流水瘦身" 的策略 ------ 既保证交易可追溯,又避免流水册无限膨胀。

相关推荐
liuzhilongDBA几秒前
论文精读|DBAIOps
数据库·postgresql·dbaiops
木风小助理2 分钟前
MySQL 存储过程与函数:核心辨析与应用指南
服务器·数据库·microsoft
普通网友10 分钟前
更优雅的测试:Pytest框架入门
jvm·数据库·python
云边有个稻草人12 分钟前
电科金仓 KES Oracle 迁移避坑:核心问题排查与解决
数据库·oracle·数据库迁移·金仓数据库
这儿有一堆花20 分钟前
JSON 与 MongoDB:直存对象的便利与隐性代价
数据库·mongodb·json
翔云 OCR API21 分钟前
API让文档信息“活”起来:通用文档识别接口-开发者文字识别API
前端·数据库·人工智能·mysql·ocr
摇滚侠22 分钟前
Redis 零基础到进阶,zset、bitmap、HyperLogLog、GEO、stream、bitfiled,笔记20-27
数据库·redis·笔记
bing.shao29 分钟前
Golang select多路复用踩坑
数据库·golang·php
摇滚侠30 分钟前
索引失效,数据库引擎,索引失效的六种情况
数据库·面试