Redis那些细节你可能没注意到,第三部分内容还是挺重要的,不看可惜
- 问答
- 2026-01-15 02:16:01
- 2
(引用来源:原作者“程序员小富”在其技术博客/公众号发布的系列文章《Redis那些细节你可能没注意到》)
第三部分主要讲的是Redis的持久化机制,特别是AOF重写这个环节里一个非常关键但又容易被忽略的细节,很多人知道Redis有两种持久化方式:RDB快照和AOF日志,RDB就像是给数据库拍一张全量照片,而AOF则是记录下每一次写操作命令,像写日记一样。
AOF的好处是数据安全性高,最多只丢失一秒的数据(如果配置为每秒同步一次的话),但时间长了,AOF文件会越来越大,比如你对一个键count连续递增了100次,AOF文件里就会记录100条INCR count命令,但其实最终状态等同于一条SET count 100,这样太占磁盘空间了,恢复起来也慢,所以Redis提供了AOF重写机制,来压缩这个“日记”,生成一个更精简的、能反映当前数据库最终状态的AOF文件。
重写的过程并不是去分析旧有的AOF文件,而是根据当前数据库的内存状态,逆向生成一系列可以重建当前数据集的命令,然后写入一个新的AOF文件,重写完成后,再用这个新文件替换掉旧的、庞大的AOF文件。
而那个容易被忽略的细节就发生在这个重写过程中,当主进程正在创建新的AOF文件时,新的写命令怎么办?
如果完全阻塞,等重写完了再处理新命令,那服务就不可用了,显然不行,Redis的处理方式是,设置一个“AOF重写缓冲区”,当主进程开始进行AOF重写时,这个缓冲区也会被同时开启。

从这一刻起,主进程在正常执行客户端的命令之外,还会同时把命令追加到两个地方:
- 正常的AOF缓冲区,用于同步到现有的AOF文件,保证原有的持久化机制照常工作。
- AOF重写缓冲区。
也就是说,在重写期间,所有新的写命令都会在主进程中被“双写”到这两个缓冲区里。
负责重写工作的是bgrewriteaof命令触发的子进程,这个子进程只拥有主进程在fork出它那一刻的内存数据快照,它基于这个快照来生成新的AOF文件,这个文件反映了那个时间点的数据状态,在子进程辛苦地生成新文件的过程中,主进程还在不停地接收新的写命令,数据库的状态已经发生了变化,这些变化只存在于主进程的内存和那个AOF重写缓冲区里,子进程是不知道的。
如果就这样不管,那么子进程生成的新AOF文件的数据就是“过时”的,用它替换旧文件就会丢失重写期间的所有写操作。

关键的一步来了:当子进程完成了新AOF文件的创建后,主进程会收到通知,然后它会将AOF重写缓冲区里积累的所有命令,追加到子进程生成的新AOF文件中,这样,新AOF文件就包含了从重写开始点到结束点之间所有的数据变更。
主进程会原子性地用这个包含了最新数据的新AOF文件,替换掉旧的AOF文件,至此,AOF重写完成,数据完整性得到了保证。
这个设计非常巧妙,它保证了在不停服的情况下,既能完成文件的压缩,又能确保数据不丢失,但这也是一个需要理解的细节,如果你不了解这个“双写”和“最后追加缓冲区”的过程,可能就会疑惑为什么重写期间的数据不会丢。
除了这个核心细节,第三部分可能还会延伸到一些相关的注意事项:
- 性能影响:虽然AOF重写是子进程在后台做的,避免了主进程阻塞,但
fork子进程的那一刻,如果主进程占用的内存非常大,fork操作本身可能会是一个耗时的操作,在某些硬件上可能会引起主进程的短暂停顿,重写过程中主进程需要双写缓冲区,也有一定的性能开销。 - 磁盘压力:重写过程需要写入一个全新的AOF文件,如果此时系统IO压力已经很大,重写操作可能会和正常的AOF日志追加写入竞争磁盘IO资源,导致性能下降。
- 异常处理:如果在重写过程中,主进程或者子进程崩溃了会怎样?这需要结合Redis的机制来理解,如果子进程崩溃,主进程会收到信号,然后将重写缓冲区的内容写回旧的AOF文件,并记录日志,重写失败,但服务继续运行,数据不会丢失,如果主进程在重写期间崩溃,那么可能情况会更复杂一些,取决于崩溃发生在哪个阶段。
理解AOF重写缓冲区这个细节,是理解Redis在提供高数据安全性的同时如何维持高可用性的关键,它不是一个简单的“后台压缩”任务,而是一个主进程和子进程协同合作、通过精巧的缓冲区设计来保证数据一致性的过程,如果不注意这个细节,可能会在评估系统性能、排查问题时走入误区。
本文由召安青于2026-01-15发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://waw.haoid.cn/wenda/80897.html