Redis 多段 AOF 文件怎么组织与重写
Redis 7.0 起,AOF 不再只由一个不断增长的文件承担全部数据,而是组织成一套多段文件:最多一个 BASE 文件、一个或多个 INCR 文件,以及负责描述有效文件集合的 manifest。BASE 表示最近一次重写时的数据基线,INCR 保存此后持续到来的增量写命令;Redis 启动时按照 manifest 指向的集合加载,而不是看到目录里有什么就把什么都重放。
BGREWRITEAOF 的关键也不再是“用一个新文件覆盖旧文件”。重写开始后,父进程会打开新的 INCR 文件继续接收写入,子进程生成新的 BASE;两者准备好后组成临时 manifest,最后通过 manifest 的原子替换让新一代集合生效,再清理不再引用的旧文件。官方持久化说明:https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/
多段 AOF 解决了什么问题
AOF 记录 Redis 接收到的写操作,重启时重放这些命令来恢复数据。问题是日志会随着写入持续增长:同一个计数器增加 100 次,最终数据集可能只需要一个键和一个结果值,但旧 AOF 中保留了 100 条增量命令。重写的目标就是用能重建当前内存数据集的更紧凑表示替代冗余历史。
Redis 7.0 以前,重写期间到来的写命令既要继续写旧 AOF,又会进入内存缓冲区;重写子进程完成后,父进程再把这段缓冲追加到新文件尾部。写入密集时,这种方式会带来额外内存、双写和重写尾部合并压力。
Redis 7.0 的多段 AOF 将“基线”和“重写期间及之后的新写入”拆成不同文件。父进程可以把新写命令直接追加到新的 INCR 文件,子进程独立构造新 BASE,最后只需要用 manifest 切换哪组文件有效。它没有取消 fork、写盘和写时复制成本,但把文件组织和切换边界变得更清楚。
| 维度 | Redis 7.0 以前 | Redis 7.0 及以上 |
|---|---|---|
| AOF 组织 | 主要是单个 AOF 文件 | BASE + 多个 INCR + manifest |
| 重写期间新写入 | 旧 AOF 与内存重写缓冲共同承接 | 父进程打开新的 INCR 文件持续追加 |
| 切换对象 | 新旧 AOF 文件 | manifest 引用的整套文件集合 |
| 失败保护 | 保留旧 AOF | 旧集合加当前 INCR 仍能表示完整数据 |
这里的“多段”不是把一个文件随意切成若干固定大小分片,也不是让运维人员按日期手工滚动。文件代际与清单都由 Redis 管理,目录中的文件名和 manifest 内容应视为持久化内部状态。
BASE、INCR 和 manifest 怎样组成可加载集合
多段 AOF 的文件放在 appenddirname 指定的独立目录中。理解目录时,先区分三个角色:
- BASE:最多一个,表示某次重写时内存数据集的基线。它可以采用 RDB 格式,也可以采用 AOF 格式。
- INCR:可以有多个,记录对应 BASE 创建后发生的增量写入。
- manifest:列出当前有效的 BASE 与 INCR 文件,是 Redis 判断加载集合的依据。

启动恢复的逻辑可以理解为:先读取 manifest,再加载 manifest 引用的 BASE,最后按清单顺序应用对应的 INCR。目录里可能短时间存在旧代文件、临时文件或等待清理的文件,仅凭文件名排序拼接并不可靠。
因此,下面几种手工操作都不安全:
- 只复制看起来最大的 BASE 文件,遗漏其后的 INCR。
- 按修改时间挑选 INCR,而不保留与之匹配的 manifest。
- 重写过程中删除“旧编号”文件,破坏当前仍有效的集合。
- 自行编辑 manifest,把未验证的文件拼成一套恢复链。
需要备份时,目标不是某一个 AOF 文件,而是一个一致的 manifest 及其引用文件集合。
最小配置与状态检查
启用 AOF 的核心配置仍然是 appendonly yes。多段组织是 Redis 7.0+ 的内部机制,不需要额外开启“分段开关”。可以在配置文件中明确目录名和刷盘策略:
# 启用 AOF 持久化 appendonly yes # 多段 AOF 文件集合使用的子目录名 appenddirname "appendonlydir" # 默认每秒刷盘,性能与可能丢失约一秒写入之间取平衡 appendfsync everysec # 允许重写产生 RDB 格式的 BASE,以缩短加载并减小体积 aof-use-rdb-preamble yes
appenddirname 是相对于 Redis 工作目录 dir 的子目录配置。不要把它和 appendfilename 简单理解为同一级的单文件路径;在多段 AOF 下,真正要管理的是目录中的整套文件。
运行中的实例可以用 INFO persistence 检查是否启用、是否正在重写、是否有待调度任务以及最近一次结果:
# 只读取持久化区段,避免在巡检时输出无关信息 redis-cli INFO persistence # 重点筛选 AOF 启用、重写进度和最近一次状态 redis-cli INFO persistence | grep -E '^(aof_enabled|aof_rewrite_in_progress|aof_rewrite_scheduled|aof_last_bgrewrite_status|aof_current_size|aof_base_size):'
常用判断可以归纳为:
| 字段 | 含义 | 运维判断 |
|---|---|---|
aof_enabled | AOF 是否启用 | 应与配置和数据安全策略一致 |
aof_rewrite_in_progress | 是否正在重写 | 为 1 时不要做依赖稳定文件集合的备份 |
aof_rewrite_scheduled | 是否等待其他持久化子进程结束后执行 | 命令返回成功不等于已经开始 |
aof_last_bgrewrite_status | 最近一次后台重写状态 | 应持续监控是否为 ok |
aof_current_size | 当前 AOF 总体大小 | 与基线大小结合判断增长幅度 |
aof_base_size | 最近启动或重写时的基线大小 | 用于理解自动重写阈值的参照 |
如果同时存在 RDB 后台保存,BGREWRITEAOF 可能只被调度,等保存子进程结束后才真正开始。这时要同时观察 rdb_bgsave_in_progress、aof_rewrite_scheduled 和 aof_rewrite_in_progress,不能只看命令返回的一行状态。
BGREWRITEAOF 如何生成新一代文件集合
BGREWRITEAOF 用于请求后台生成更紧凑的 AOF。命令本身的时间复杂度标记为 O(1),但这只描述命令触发动作,不代表后台重写没有成本。实际重写需要遍历当前数据集、生成新 BASE、维护增量写入并落盘。
# 请求后台重写;成功回复可能表示已开始,也可能表示已调度 redis-cli BGREWRITEAOF # 持续查看真实状态,直到进行中与待调度字段都归零 redis-cli INFO persistence
Redis 7.0+ 的文件关系可以按下面的边界理解:
- 现行 manifest 继续引用旧 BASE 和旧 INCR,这套集合在重写完成前仍然有效。
- 父进程打开一个新的 INCR,用它持续接收重写期间到来的写命令。
- 子进程基于 fork 时刻的数据视图生成新的 BASE 临时文件。
- 新 BASE 与新 INCR 准备好后,Redis 构造并持久化临时 manifest。
- Redis 原子替换 manifest,使新一代文件集合生效,然后清理旧 BASE 和未再引用的 INCR。

这个设计的重要安全点是:切换发生在 manifest 层。新 BASE 尚未完成时,现行 manifest 仍指向旧集合;重写期间的新写入已经进入新 INCR。即使重写失败,旧 BASE、旧 INCR 加上这份新打开的 INCR 仍能表示更新后的完整数据,Redis 不需要让一个半成品 BASE 取代稳定集合。
官方命令说明也明确指出:如果 BGREWRITEAOF 失败,旧 AOF 不会因此被破坏。若已有 AOF 重写正在进行,再次调用会返回错误;若正在执行 RDB 保存,重写会被安排在该子进程结束后开始。
自动重写怎样触发
Redis 可以根据当前 AOF 大小相对基线的增长比例自动触发重写。常见配置由一个百分比和一个最小体积共同控制:
# 当前 AOF 相对基线增长到 100% 时具备自动重写条件 auto-aof-rewrite-percentage 100 # 文件至少达到 64mb 才触发,避免小数据集频繁重写 auto-aof-rewrite-min-size 64mb
只有百分比而没有最小体积,小实例也可能因相对增长很快而频繁重写;只有最小体积而没有增长比例,又可能让冗余日志长期累积。阈值应结合写入速率、可用内存、磁盘吞吐、恢复时间目标和重写耗时设置。
Redis 还会限制连续失败后的重试节奏,避免失败重写不断创建更多 INCR 文件并反复消耗资源。运维上不应只等待自动重试,而要检查最近一次重写状态、系统日志、磁盘空间、权限和 fork 失败原因。
兼容与迁移时要注意什么
Redis 7.0 前后的目录模型不同
Redis 7.0 以前通常围绕单个 AOF 文件做备份、监控和清理;升级后需要把工具改成“目录 + manifest 引用集合”的认知。仍然只复制 appendonly.aof 的旧脚本,可能无法获得完整备份。
BASE 可能是 RDB 格式
当 aof-use-rdb-preamble yes 时,BASE 可以用紧凑的 RDB 格式保存,后续 INCR 仍是 AOF 增量命令。这不代表实例退回了纯 RDB 持久化;恢复时仍由 manifest 组织 BASE 与 INCR 的完整集合。
不要把版本降级当作文件复制
多段 AOF 是 Redis 7.0+ 的持久化格式边界。需要降级到不理解该格式的旧版本时,应按照目标版本兼容文档设计数据迁移和回滚,不应假设把目录改名或把多个文件拼成一个文件就能安全启动。
从 RDB 切换到 AOF 要在运行实例上完成
官方建议在当前运行的 Redis 上通过配置命令启用 AOF,让 Redis 基于内存数据生成初始持久化集合,并把配置持久化到配置文件。只改配置文件后直接重启,可能让新实例找不到包含最新数据的 AOF。
# 在运行实例上启用 AOF,让 Redis 生成初始文件集合 redis-cli CONFIG SET appendonly yes # 把有效配置写回配置文件,避免重启后回到旧设置 redis-cli CONFIG REWRITE # 等待重写结束,并确认最近一次状态正常 redis-cli INFO persistence
执行前先备份最新 RDB,并根据权限与变更流程安排窗口。启用后还要确认写命令确实进入 AOF、重写状态结束,以及重启前后的关键数据量与业务校验一致。
备份多段 AOF 不能边重写边随意复制
正常运行时,完整复制或打包 appenddirname 目录即可取得多段 AOF 文件集合;但如果复制过程与 AOF 重写重叠,可能把旧 manifest、新 BASE 和不同代 INCR 混在一起,得到不可恢复的组合。
官方给出的基本思路是:临时关闭自动重写,确认没有重写正在进行,复制整个目录,完成后再恢复原阈值。操作时要记录原配置值,而不是一律恢复为示例数字:
# 临时关闭自动重写;先记录原值,完成后必须恢复 redis-cli CONFIG SET auto-aof-rewrite-percentage 0 # 确认 aof_rewrite_in_progress 为 0 后再复制整个 appenddirname redis-cli INFO persistence # 复制完成后恢复变更前的百分比,不要盲目使用固定值 redis-cli CONFIG SET auto-aof-rewrite-percentage
这里还要避免手工调用 BGREWRITEAOF。如果希望缩短暂停自动重写的时间,可以先为目录中的不可变文件创建硬链接,再恢复重写设置,随后从硬链接集合复制;是否采用该方案取决于文件系统和备份工具能力。
性能与安全边界
多段 AOF 降低了 Redis 7.0 以前重写尾部缓冲的一部分压力,但重写依然不是“零成本”:
- fork 延迟:数据集越大、页表越多,创建子进程可能越慢。
- 写时复制:重写期间持续写入会让被修改内存页复制,额外内存应通过
current_cow_peak、aof_last_cow_size等指标观察。 - 磁盘带宽:子进程写新 BASE,父进程写 INCR,若与备份或 RDB 保存争抢磁盘,延迟可能上升。
- fsync 策略:
always、everysec和no的性能与数据丢失窗口不同;多段文件不会改变这一基本取舍。 - 磁盘空间:重写完成前,新旧两代文件可能同时存在,需要预留高于单套 AOF 的空间。
生产巡检可以同时关注持久化和系统资源,而不是只盯一个“重写成功”字段:
# 查看 AOF 当前大小、基线大小、重写状态与 COW 指标 redis-cli INFO persistence # 查看延迟事件,结合系统监控定位 fork 或磁盘抖动 redis-cli LATENCY LATEST # 查看当前工作目录与 AOF 子目录配置,确认容量监控覆盖正确路径 redis-cli CONFIG GET dir redis-cli CONFIG GET appenddirname
Redis 管理命令通常属于敏感运维权限。生产环境应通过 ACL 限制 BGREWRITEAOF、CONFIG、INFO 等命令的调用范围,不要为了方便巡检而向普通应用账号开放完整管理权限。
一份可执行的检查清单
- 确认实例版本为 Redis 7.0 或更高,监控脚本已经适配多段 AOF。
- 确认
appendonly、appenddirname、appendfsync与恢复目标一致。 - 确认容量监控覆盖整个 AOF 子目录,而不是只匹配单个旧文件名。
- 观察
aof_rewrite_in_progress、aof_rewrite_scheduled和aof_last_bgrewrite_status。 - 记录重写耗时、COW 峰值、磁盘吞吐、延迟和重写前后总体积。
- 备份时暂停自动与手工重写,并复制完整目录及 manifest 引用集合。
- 定期在隔离环境做恢复演练,不能把“文件复制成功”等同于“可恢复”。
- 重写失败时保留现场与旧集合,先查磁盘、权限、fork 和系统日志,不手工删文件。
常见问题
为什么目录里会有多个 INCR?
每次重写开始时,父进程都可能打开新的 INCR 来接收后续写入。重写失败或重试时,为保证数据链完整,旧集合与新开的 INCR 可能同时保留;Redis 会限制连续失败后的重试节奏,并在成功切换后清理不再使用的文件。
可以只备份 BASE 吗?
不可以把 BASE 当成最新完整状态。BASE 只代表最近一次基线,之后的写入在 INCR 中。恢复需要 manifest 指定的完整 BASE 与 INCR 集合。
BGREWRITEAOF 返回成功就代表完成了吗?
不代表。成功回复只说明重写已启动或已被调度。应使用 INFO persistence 等待 aof_rewrite_in_progress 和 aof_rewrite_scheduled 都为 0,并检查 aof_last_bgrewrite_status。
多段 AOF 会消除重写期间的内存压力吗?
不会。它减少了 Redis 7.0 以前重写缓冲与双写造成的一部分问题,但 fork 和写时复制仍会消耗内存。写入越密集,重写期间被修改的内存页越多,COW 峰值越值得关注。
manifest 能手工修复吗?
不建议把手工编辑 manifest 作为常规修复方案。先保留完整副本,查看 Redis 日志和官方修复工具适用范围,并在隔离环境验证恢复。清单、BASE 与 INCR 必须属于一致文件代,误配可能造成启动失败或数据缺失。
把多段 AOF 理解成“manifest 管理的一组不可随意拆分的持久化对象”,就能抓住组织与重写的核心:BASE 提供基线,INCR 接续变化,manifest 决定哪一代集合有效,原子清单切换保证半成品不会替换稳定数据。
漫狐高清画质怎么理解?页面功能、阅读体验与使用边界说明
- 上一篇
- 漫狐高清画质怎么理解?页面功能、阅读体验与使用边界说明
- 下一篇
- magisk v31.0 更新了什么?界面重写、内置终端与 Android 17 支持说明
-
- 数据库 · Redis | 3小时前 |
- Redis Sorted Set 怎么按字典序分页
- 265浏览 收藏
-
- 数据库 · Redis | 7小时前 | Redis ·
- Redis 客户端缓存 Tracking 模式怎么选择
- 196浏览 收藏
-
- 数据库 · Redis | 14小时前 | Redis ·
- Redis XINFO 观测消费者组积压的指标清单
- 132浏览 收藏
-
- 数据库 · Redis | 1天前 | Redis · 向量检索 · redis VADD VSIM Vector Sets
- Redis Vector Sets 存储相似度结果的查询组织
- 449浏览 收藏
-
- 数据库 · Redis | 2天前 | Redis ·
- Redis Pub/Sub 与 Streams 事件可靠性的对比
- 270浏览 收藏
-
- 数据库 · Redis | 2天前 | Redis · 高并发 · 分布式系统 · 幂等 库存扣减 Redis Functions FCALL
- Redis Functions 部署库存扣减逻辑的幂等边界
- 468浏览 收藏
-
- 数据库 · Redis | 5天前 |
- Redis ZSET 实现延迟队列的分数设计
- 394浏览 收藏
-
- 数据库 · Redis | 5天前 | 事务 · redis集群 · redis 原子操作 Redis Cluster Hash Tag 多 key
- Redis Cluster Hash Tag 组织多 key 原子操作
- 357浏览 收藏
-
- 数据库 · Redis | 5天前 | 消息队列 · redis 消费者组 XAUTOCLAIM Redis Streams pending消息
- Redis 消费者组 pending 消息的认领与恢复流程
- 101浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 325次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 382次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 376次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 342次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 167次使用
-
- 新能源汽车充电设施巡检记录的设置方法
- 2026-10-04 422浏览
-
- Go与Redis实现分布式互斥锁和红锁
- 2022-12-22 117浏览
-
- Go+Redis实现延迟队列实操
- 2023-02-23 426浏览
-
- 一文搞懂Go语言操作Redis的方法
- 2023-01-07 171浏览
-
- Golang分布式应用之Redis示例详解
- 2023-01-07 113浏览

