news 2026/10/11 1:55:59

Redis-一文吃透 Redis 持久化:RDB 快照与 AOF 日志

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis-一文吃透 Redis 持久化:RDB 快照与 AOF 日志

一文吃透 Redis 持久化:RDB 快照与 AOF 日志(含 AOF 重写全流程)

为什么要有这篇博客?
Redis 的数据全都放在内存里——内存虽快,却是易失性存储:一旦进程退出、服务器宕机,内存里的数据就会全部丢失。为了解决这个问题,Redis 提供了两种持久化方式,把内存数据保存到硬盘上,下次重启时再加载回来,保证数据的可持久性(Durability)。


目录

  • 一、为什么要持久化
  • 二、RDB:内存快照
    • 2.1 触发机制
    • 2.2 bgsave 的运作流程(重点)
    • 2.3 RDB 的优缺点
  • 三、AOF:写命令日志
    • 3.1 AOF 的工作流程
    • 3.2 文件同步策略 appendfsync
    • 3.3 AOF 的优缺点
  • 四、AOF 重写机制(重点)
    • 4.1 为什么需要重写
    • 4.2 重写的触发方式
    • 4.3 重写的完整流程(逐步详解)
  • 五、启动时数据恢复
  • 六、总结与对比

一、为什么要持久化

Redis 是一个内存键值数据库——数据平时只存在于内存中。内存带来了微秒级的读写速度,这是 Redis 高性能的根基;但内存有一个致命属性:断电即失。

如果没有任何持久化措施:

  • Redis 进程崩溃 → 数据全部丢失;
  • 服务器断电重启 → 数据全部丢失;
  • 想做主从复制、灾难备份 → 无从谈起。

❗一句话总结:内存负责「快」,硬盘负责「不丢」。持久化就是 Redis 把内存数据写到硬盘的过程,Redis 提供了两种策略——RDB(快照)和 AOF(日志)。


二、RDB:内存快照

RDB(Redis Database)持久化是把当前进程中的数据生成快照保存到硬盘的过程,产生的文件是一个紧凑的二进制文件(默认dump.rdb)。

2.1 触发机制

RDB 的触发分为手动触发和自动触发两类。

手动触发对应两个命令:

命令行为是否阻塞
save阻塞当前 Redis 服务器,直到 RDB 过程完成为止❌ 全程阻塞,内存大的实例会长时间卡住,基本不用
bgsaveRedis 进程执行fork创建子进程,RDB 持久化由子进程负责✅ 只在 fork 阶段短暂阻塞

❗ Redis 内部所有涉及 RDB 的操作都采用类似bgsave的方式。

自动触发(实战中真正有价值的部分):

  1. save 配置:save m n表示m 秒内数据集发生了 n 次修改,就自动触发 RDB 持久化(如save 900 1);
  2. 从节点做全量复制时,主节点自动执行 RDB 持久化,随后把 RDB 文件内容发送给从节点;
  3. 执行shutdown命令关闭 Redis 时,会执行一次 RDB 持久化。

2.2 bgsave 的运作流程(重点)

对照上图,bgsave 共分 5 步:

  1. 执行 bgsave 命令:Redis 父进程判断当前是否存在其他正在运行的子进程(比如正在执行 RDB/AOF),如果存在,bgsave 直接返回,不执行;
  2. 父进程执行 fork 创建子进程:fork 过程中父进程会阻塞(可通过info stats查看latest_fork_usec选项获取最近一次 fork 的耗时,单位微秒);
  3. fork 完成后立即放行:bgsave 命令返回"Background saving started",父进程不再阻塞,继续响应其他命令;
  4. 子进程创建 RDB 文件:子进程根据父进程的内存数据生成临时快照文件(temp-xxx.rdb),完成后对原有 RDB 文件进行原子替换(可用lastsave命令查看最后一次生成 RDB 的时间);
  5. 子进程向父进程发送信号,表示完成,父进程更新统计信息。

💡为什么子进程能"拍"到父进程内存的快照?
这依赖 Linux 的写时复制(Copy-On-Write,COW)机制:fork 出的子进程与父进程共享同一份物理内存,只有当父进程发生写操作时,才会真正复制被修改的那一页数据。因此子进程拿到的永远是fork 那一刻的干净数据副本,而父进程可以照常接受写入——两边互不干扰。

💡RDB 文件的处理:文件保存在dir配置指定目录(文件名dbfilename,默认 dump.rdb);Redis 默认采用LZF 算法对 RDB 文件压缩,体积远小于内存数据量;Redis 还会对文件做校验,启动时加载到损坏的 RDB 文件会拒绝启动(可用redis-check-dump工具检测修复)。

2.3 RDB 的优缺点

优点:

  • RDB 是一个紧凑压缩的二进制文件,代表某个时间点上的数据快照,非常适合备份、全量复制等场景(比如每 6 小时执行 bgsave,并把文件复制到远程机器);
  • Redis 加载 RDB 恢复数据的速度远远快于 AOF。

缺点:

  • 没办法做到实时/秒级持久化:bgsave 每次运行都要执行 fork 创建子进程,属于重量级操作,频繁执行成本过高;所以两次快照之间写入的数据,宕机时就丢了;
  • RDB 使用特定二进制格式保存,Redis 版本演进过程中有多个 RDB 版本,老版本兼容性可能存在问题。

三、AOF:写命令日志

AOF(Append Only File)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF 文件中的命令,达到恢复数据的目的。

如果说 RDB 是「给内存拍照片」,那 AOF 就是「把每一笔账都记在本子上」——它的主要作用是解决数据持久化的实时性,是目前 Redis 持久化的主流方式。

3.1 AOF 的工作流程

开启 AOF 需要配置appendonly yes(默认不开启),文件名由appendfilename配置(默认appendonly.aof)。

AOF 的工作流程共 4 步:

  1. 命令写入(append):所有的写入命令会追加到 **aof_buf(缓冲区)**中。AOF 记录的内容是 Redis 文本协议格式,例如set hello world会追加:*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n;
  2. 文件同步(sync):AOF 缓冲区根据对应的策略向硬盘做同步操作;
  3. 文件重写(rewrite):随着 AOF 文件越来越大,需要定期对文件进行重写,达到压缩的目的(详见第四章);
  4. 重启加载(load):当 Redis 服务器启动时,可以加载 AOF 文件进行数据恢复。

❗为什么需要 aof_buf 缓冲区?
Redis 使用单线程响应命令,如果每次写命令都直接同步硬盘,性能就会从「内存读写」降级为「IO 读写」。先写入缓冲区可以有效减少 IO 次数,同时 Redis 还提供多种缓冲区同步策略,让用户在「安全性」和「性能」之间自由权衡。

3.2 文件同步策略 appendfsync

Redis 提供了三种 AOF 缓冲区同步文件策略,由参数appendfsync控制:

可配置值含义特点
always命令写入 aof_buf 后立即调用 fsync同步,完成后返回最安全,但性能很差(SATA 硬盘只有几百 TPS),非极重要数据不建议
everysec命令写入 aof_buf 后只执行 write,每秒由后台线程 fsync 一次默认配置、推荐配置,兼顾安全与性能,最多丢 1 秒数据
no只执行 write,fsync 频率交给操作系统决定性能最好,但丢失风险大,一般不建议

💡write 与 fsync 的区别:write只是把数据写进内核的页缓冲区就立即返回(宕机时缓冲区数据可能丢失);fsync针对单个文件做强制硬盘同步,会阻塞直到数据真正写到磁盘。

3.3 AOF 的优缺点

优点:

  • 实时性远好于 RDB(everysec 策略最多丢 1 秒数据),是目前的主流持久化方式;
  • 文本是可读的命令协议,兼容性好、实现简单。

缺点:

  • AOF 文件是命令日志,相同的数据往往占据比 RDB 更大的体积;
  • 恢复时需要逐条重放命令,加载速度慢于 RDB;
  • 文件会随命令不断增大——这就引出了下面的重写机制。

四、AOF 重写机制(重点)

4.1 为什么需要重写

随着命令不断写入 AOF,文件会越来越大。但文件里其实有大量「废话」:

  • 对同一个 key 反复修改,只有最后一次是有效的;
  • del、hdel、srem等删除命令留下的痕迹毫无意义;
  • 已经过期的数据还躺在文件里;
  • 对同一个 list 连续lpush list a、lpush list b、lpush list c,完全可以合并成一条。

**AOF 重写(rewrite)**就是把这些冗余压缩掉:把 Redis 进程内的当前数据直接转化为最终状态的写命令,同步到一个全新的 AOF 文件,最后用它替换旧文件。重写后的 AOF 体积更小 → 硬盘占用更少 → 启动恢复速度更快。

4.2 重写的触发方式

  • 手动触发:调用bgrewriteaof命令;
  • 自动触发:由两个参数共同决定:
    • auto-aof-rewrite-min-size:触发重写时 AOF 的最小文件体积,默认64MB(低于这个大小从不重写);
    • auto-aof-rewrite-percentage:当前 AOF 文件大小相对于上次重写后大小的增长比例,达到比例就自动触发。

4.3 重写的完整流程(逐步详解)


对照上图,重写流程如下:

① 执行 AOF 重写请求:如果当前正在执行 AOF 重写,本次请求不执行;如果正在执行bgsave,重写命令延迟到 bgsave 完成之后再执行;

② 父进程执行 fork 创建子进程;

③ 重写期间,父子进程各干各的(最关键的一步):

  • 父进程(3.1):fork 之后继续响应其他命令,所有修改操作照常写入aof_buf,并按 appendfsync 策略同步到旧 AOF 文件——保证旧 AOF 文件机制在整个重写期间依然正确,万一重写失败,数据安全不受影响;
  • 子进程(3.2):子进程只有fork 之前的内存数据;fork 之后父进程发生的修改,父进程会**再写一份到 AOF 重写缓冲区(aof_rewrite_buf)**中;

④ 子进程写新文件:子进程根据内存快照,把数据转化为最终状态的写命令,合并写入新的 AOF 文件;

⑤ 收尾(信号通知 + 补课 + 替换):

  • 5.1 新文件写入完成后,子进程发送信号通知父进程;
  • 5.2 父进程把重写缓冲区中保存的命令(即 fork 之后的增量修改)追加到新 AOF 文件——保证新文件也是最新的;
  • 5.3新 AOF 文件原子替换旧 AOF 文件,重写完成。

❗一句话理解双缓冲区:aof_buf 保证「旧 AOF 始终可用」(保底),aof_rewrite_buf 记录「fork 之后的增量」(补课)——两者配合,让重写全程无锁、不停服、随时可失败回退。


五、启动时数据恢复

当 Redis 启动时,会根据 RDB 和 AOF 文件的内容进行数据恢复:

  • 开启了 AOF→ 优先加载 AOF 文件恢复数据(AOF 更完整);
  • 没有开启 AOF→ 尝试加载 RDB 文件;
  • 两者都没有 → 空库启动;
  • 文件损坏时 Redis 会拒绝启动,可用redis-check-rdb/redis-check-aof工具检测修复。

六、总结与对比

对比项RDBAOF
本质内存数据的二进制快照写命令的文本日志
实时性差(两次快照之间的数据会丢)好(everysec 最多丢 1 秒)
文件体积小(紧凑压缩)大(有重写机制压缩)
恢复速度快(直接载入二进制)慢(逐条重放命令)
主要用途冷备、主从全量复制实时持久化(主流方案)
核心命令bgsavebgrewriteaof

❗本章重点回顾:

  1. Redis 提供了 RDB 和 AOF 两种持久化方案:RDB 视为内存的快照,内容紧凑、恢复快,但开销较大、不适合实时持久化,一般用于冷备和主从复制;AOF 保存的是修改命令,恢复时需要重放,并有重写机制定期压缩文件;
  2. RDB 和 AOF 都使用fork 创建子进程,利用 Linux 父子进程共享内存(写时复制)的特点进行持久化,尽可能不影响主进程继续处理命令;
  3. AOF 的重写依靠aof_buf + aof_rewrite_buf 双缓冲区配合,做到不停服、数据安全;
  4. 生产环境的经典选择:AOF(everysec)保实时 + RDB 定期做冷备,两者互补。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/11 1:55:29

FreeCAD源码分析:Externsion机制

本文分析FreeCAD中Extension机制的实现。 注1:限于研究水平,文中分析难免有不当之处,欢迎批评指正。 注2:本文档将不定期更新。 一、机制概览 FreeCAD 的文档对象(App::DocumentObject)需要同时支持几何、分…

作者头像 李华
网站建设 2026/10/11 1:55:07

个人核心技能(Skills)实战应用与价值转化指南

很多开发者在职业生涯的某个阶段都会遇到类似的瓶颈:技术栈似乎很全,但面对新的业务挑战时总觉得使不上劲;或者明明加班不少,却在晋升答辩或跳槽面试时拿不出令人信服的亮点。这种焦虑往往不是因为我们不够努力,而是缺…

作者头像 李华
网站建设 2026/10/11 1:53:28

hot100 p0——栈,贪心算法,动态规划

栈 有效的括号 20. 有效的括号 - 力扣(LeetCode) 给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号…

作者头像 李华
网站建设 2026/10/11 1:53:02

同步FIFO详细verilog代码及其 tb代码

// // 同步 FIFO (视见数量 / 水位线版)//// 设计依据// 写端视见数据量 WCNT WPTR - Delayed(RPTR) 实际 delta -> 写端多看数据、少看空位// 读端视见数据量 RCNT Delayed(WPTR) - RPTR 实际 - delta -> 读端少看数据、多看空位/…

作者头像 李华
网站建设 2026/10/11 1:52:22

WPF中的依赖属性

依赖属性在传统的c#开发中,我们使用的是CLR 公共语言运行时,属性。它的本质是封装了一个私有字段,每次new一个对象,无论这个属性用不用,系统都会在内存中为这个字段分配空间。而依赖属性 彻底颠覆了这个设置&#xff1…

作者头像 李华