Redis重写到底是咋回事,原理那些复杂但又挺有意思的细节解析
- 问答
- 2026-01-08 15:49:06
- 3
Redis重写,说白了就是给Redis这个超级快的“内存大仓库”做一次大扫除和整理归档,目的是为了让它的核心文件——AOF文件或者RDB文件——变得更小、更干净,同时还能保证数据一点不丢,这事儿听起来简单,但里面的门道挺有意思,咱们分开说两种主要的重写。
AOF重写:把“流水账”变成“总结报告”
你可以把AOF(Append Only File)文件想象成Redis记的一本超级详细的“操作流水账”,你每下达一个命令,set name jack,Redis就立刻把这行命令原封不动地记到账本里,时间长了,这个账本会变得非常厚。
你对同一个键 count 操作了100次:
set count 1incr countincr count...incr count
账本里就会密密麻麻记上100行命令,但明眼人一看就知道,最终这个 count 的值就是100,前面99条记录其实都是“废话”,最终的結果才是最重要的,AOF重写干的就是这个“聪明人”的活儿:它不会去傻乎乎地复制这100条命令,而是会直接查看当前内存里 count 的值是多少,然后生成一条最终极、最简洁的命令:set count 100。

这个过程是怎么做到不影响正常服务的呢?Redis用了一个非常巧妙的“父子进程”协作模式(根据《Redis设计与实现》这本书里的描述)。
- fork一个“儿子”: 当Redis决定要重写AOF时,它会调用操作系统的
fork()函数,瞬间创建一个和自己一模一样的“子进程”,这个子进程拥有父进程此刻内存数据的完全副本,注意,是“副本”,所以之后父进程继续处理新命令,修改的是原来的内存数据,而子进程面对的是它自己那份不会变的“快照”。 - 儿子负责“写总结”: 子进程就安心地、慢慢地遍历自己那份内存数据快照,根据每个键的当前值,生成一系列最精简的Redis命令,然后写入一个新的、临时的AOF文件中,这个过程因为不需要处理新的网络请求,所以可以全力进行IO写入,效率很高。
- 父亲负责“记新账”: 在儿子忙着写总结报告的时候,父亲(主进程)可没闲着,它还在正常接收客户端的命令,为了保证重写期间的新数据不丢失,父亲会把这些新命令不仅写入原来的AOF文件,还会同时塞进一个叫做“AOF重写缓冲区”的内存区域里,这个缓冲区就像个临时记事本。
- 父子汇合,查漏补缺: 当儿子终于把那份庞大的总结报告(新的AOF文件)写完后,它会通知父亲,父亲这时就行动起来,把“临时记事本”(AOF重写缓冲区)里积攒的所有新命令,再追加到儿子生成的新AOF文件末尾,这样,新文件就既包含了重写时刻的数据快照(由儿子完成),又包含了重写过程中产生的新数据(由父亲追加),数据就完整了。
- 新旧交替: 父亲会用这个全新的、更小的AOF文件,原子性地替换掉那个臃肿的旧AOF文件,大扫除完成!
RDB重写:其实就是拍个“全家福”
RDB重写相对就直白多了,RDB文件是Redis在某个时间点的完整数据快照,就像给整个数据库拍一张“全家福”照片。

所谓的RDB“重写”,其实就是重新拍一张新的全家福,这个过程同样使用了上面提到的 fork() 子进程的方式:
- 主进程fork一个子进程。
- 子进程将内存中所有数据以二进制的紧凑格式序列化,并写入一个临时的RDB文件。
- 写完后,用这个新的RDB文件替换掉旧的。
那为什么RDB也需要“重写”呢?因为Redis有可能会配置成同时使用AOF和RDB,或者在某些情况下,手动执行 BGSAVE 命令来生成RDB备份,这个生成的过程本质上就是一次RDB的重写。
触发时机和意义
这两种重写都不是随便发生的,主要有两种情况:
- 自动触发: 你可以给Redis设置一个阈值,比如当AOF文件比上次重写后大了100%,就自动触发AOF重写,这就像你规定“当流水账本厚度翻倍时,就必须做一次总结”。
- 手动触发: 通过向Redis发送
BGREWRITEAOF或BGSAVE命令,手动启动重写过程。BG开头的意思就是“后台”执行,不会阻塞服务。
Redis重写的核心价值就在于:用最小的磁盘空间和IO代价,来保证数据的持久化完整性。 它通过巧妙的进程分离技术,做到了在“大扫除”的同时,服务还能正常对外营业,几乎感觉不到卡顿,这种设计思想,在追求高性能的系统中非常经典。
本文由革姣丽于2026-01-08发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/76894.html
