引言:在Redis中,持久化是确保数据持久性和可恢复性的重要机制之一。除了常见的RDB(Redis Database)持久化方式外,AOF(Append Only File)也是一种常用的持久化方式。AOF持久化通过记录Redis服务器执行的写命令来实现数据的持久化。本文将探讨AOF重写机制的原理、实现方式以及其在Redis持久化中的作用,以帮助读者更好地理解和利用Redis中的AOF持久化机制。
题目
什么是 AOF 重写?AOF 重写机制的流程是什么?
推荐解析
什么是 AOF 重写?
AOF (Append Only File)是 Redis 持久化的一种方式,其通过记录 Redis 执行的每一条命令,重启之后通过重新执行 Redis 中的命令来恢复数据。
不过,随着 Redis 执行命令的不断增多,AOF 文件越来越大,但是很多数据其是不一定都是有意义的,比如原来 set age 10,后面又来个 set age 18,然后又来个 set age 30,我们这个时候就会发现,只有最后一个 age 是有意义的,前面都是没有用的。
AOF 重写就是指通过当前状态,重新生成最新的 AOF 操作命令记录的过程。
AOF 的重写流程?
AOF 文件的重写流程主要就一句话,“一次拷贝,两处日志”。
- 一次拷贝:重写发生的时候,主进程会 fork 出一个子进程,然后子进程与主进程共享 Redis 物理内存,让子进程将这些 Redis 数据写入重写日志。
- 两处日志:重写发生的时候,我们需要注意 AOF 缓冲和 AOF 重写缓冲;当数据进行重写的时候,如果此时有新的写入命令执行,会由主进程分别写入 AOF 缓冲和 AOF 重写缓冲;AOF 缓冲用于保证此时即使发生宕机了,原来的 AOF 日志也是完整的,可以用于恢复。AOF 重写缓冲用于保证新的 AOF 文件也不会丢失最新的写入操作。
AOF 的重写流程大致就是这样了,相信到这里大家只要熟读八股文,那肯定是没有任何问题的,接下里面试官肯定会问那有什么办法可以优化呢?一般人都会回答 RDB + AOF 的混合持久化,90 % 的人都会这样回答,但是这样的回答面试官听太多了,那有什么办法可以优化一下呢?必须有的,接下来就是我们今天文章的主角 Multi Part AOF。
原有 AOF 重写的弊端
我们先来分析一下原先的方案,其流程图主要如下所示:
这个弊端主要有 3 个方面的内容,在这里我总结一下:
1)内存开销: 在进行 AOF 重写的时候,AOF 缓冲与 AOF 重写缓冲区中的内容是一致的,这样就代表一样的内容得写两遍,带来了不必要的内存开销;
2)磁盘开销:在重写的时候,AOF 缓冲区需要刷盘旧的日志文件到新的 AOF 日志,而 AOF 重写缓冲区的内容需要绕过一段很长的链路写入到新的 AOF 日志,两份的数据明明是一样的,但是却需要磁盘两次写入,这也带来了不必要的磁盘开销;
3)CPU 开销: 在进行 AOF 重写的时候,主进程需要将新写入的数据写入到 AOF 重写缓冲区当中,主进程还需要通过管道将 AOF 重写缓冲区的的数据发送给子进程,然后子进程还需要将这些数据写入到新的日志文件。由于 Redis 的读写操作单线程的,这些操作都是串行执行的,所以会带来不必要的 CPU 开销。
在这个过程中,我们会发现两个核心点:
1)AOF 重写缓冲区和 AOF 缓冲区内的数据是一样的;
2)父子进程之间传输数据这个操作耗时太久了;
以下是 Redis 的官方文档,我们会发现 7.0 之前就是我们所说的点,既然官方都说这个是 Redis 7.0 之前了,那 Redis 7.0 之后发生了什么呢,接下来让我们来探究一下今天的主角 MP-AOF。
Multi Part AOF
千呼万唤始出来,Multi Part AOF 出来了,以下是官方文档对他的一端描述
Since Redis 7.0.0, when an AOF rewrite is scheduled, the Redis parent process opens a new incremental AOF file to continue writing. The child process executes the rewrite logic and generates a new base AOF. Redis will use a temporary manifest file to track the newly generated base file and incremental file. When they are ready, Redis will perform an atomic replacement operation to make this temporary manifest file take effect. In order to avoid the problem of creating many incremental files in case of repeated failures and retries of an AOF rewrite, Redis introduces an AOF rewrite limiting mechanism to ensure that failed AOF rewrites are retried at a slower and slower rate.
官方文档地址:https://redis.io/topics/persistence
你会发现他说的全是英文,其实核心已经藏在他的名字里了 Multi Part AOF, 即将原来一个 AOF 文件拆分成多个 AOF 文件,在 Multi Part AOF 中,文件被分成 3 种类型,分别如下:
- Base: 表示基于 AOF 文件,记录了基本的命令,一般由子进程通过重写产生,只有一个。
- Incr:表示增量 AOF 文件,记录了重写过程中新增的操作指令,一般会在 AOF 重写开始执行时被创建,该文件可能存在多个。
- History:表示历史 AOF 文件,他主要由 Base 和 Infr 变化而来,每次 AOF 重写完成后,本次 AOF 重写之前对应的 Base 和 Incr 的 AOF 文件都会变成 Histroy,History 类型的 AOF 会被 Redis 自动删除。
然后为了管理 AOF 文件,我们引入了一个 mainfest(清单)文件来跟踪和管理这些 AOF。于此同时,为了方便 AOF 备份和拷贝,我们将所有的 AOF 文件和 mainfest 文件放到一个单独的目录文件目中,目录文件名由 appenddirname配置(Redis 7.0新增配置项)决定。
下图是 Multi Part AOF 的流程:
从图中我们可以看到,现在重写阶段,只需要在主进程中将新请求数据写到 AOF 缓存中就可以了,然后 AOF 缓冲区的文件最后形成 Incr AOF 日志的内容,然后在子进程中,根据数据库 fork 的数据,生成一个 Base AOF 文件,两者合一构成 Redis 的全部数据。
然后在 AOF 重写结束后,主进程会更新 mainifest 文件的内容,将新生成的 Base AOF 文件和 Incr AOF 文件的内容加入,并且将之前的 Base AOF 文件和 Incr AOF 文件标记为 Histroy,然后等待 Redis 异步删除。
到此为止,我们会发现一件事,现在的 AOF 重写有了很大的改进:
- 在 AOF 重写期间不需要 AOF 重写缓冲区了
- 然后也不需要父子进程通过管道进行数据传输
从一定程度上减缓了 CPU、内存、磁盘的性能损耗,也降低了 Redis 的代码复杂度。
总结
原有的 AOF 重写由于引入了 AOF 重写缓冲区以及父子进程通信,导致了 Redis CPU、磁盘、内存的性能损耗,Redis 7.0 引入了 MP-AOF 的方案进行优化,到这里为止,各位以后说 AOF 持久化优化的时候又多了一个装逼的点,直接和面试官说我看过 Redis 的官方文档,这样不就加大分了嘛,好了,到这里就结束了,小伙伴们赶紧学起来吧。
其他补充
鱼聪明 AI 的回答:
鱼聪明 AI 地址:https://www.yucongming.com/
Redis 提供了两种主要的持久化机制,分别是 RDB(Redis DataBase)和 AOF(Append Only File)。这两种机制可以确保 Redis 服务器在重启时能够恢复数据,但它们的工作原理和恢复流程略有不同。
RDB 持久化
RDB 是 Redis 的一种快照持久化方式,它可以将 Redis 内存中的数据保存到硬盘上的一个文件中。RDB 的恢复流程如下:
- 生成 RDB 文件:
- Redis 服务器根据设定的策略(如定期快照或手动触发)生成 RDB 文件。
- 在生成 RDB 文件期间,Redis 会阻塞所有客户端请求,以确保数据的一致性和完整性。
- 保存 RDB 文件:
- 一旦生成完毕,RDB 文件会被保存到硬盘上指定的位置。这个位置可以在 Redis 配置文件中进行配置。
- 恢复过程:
- 当 Redis 服务器重启时,它会尝试加载最近保存的 RDB 文件。
- 如果 RDB 文件存在且没有损坏,Redis 会从中读取数据并加载到内存中,完成恢复过程。
- 一旦加载完成,Redis 就可以继续接受客户端请求。
AOF 持久化
AOF 是一种基于日志的持久化方式,它通过记录 Redis 服务器接收到的每个写操作来实现数据持久化。AOF 的恢复流程如下:
- AOF 文件:
- Redis 将每个写操作追加到 AOF 文件的末尾。AOF 文件包含一个完整的操作日志,描述了服务器执行的所有写操作。
- 重放 AOF 文件:
- 当 Redis 服务器重启时,它会尝试通过重放 AOF 文件中的写操作来重建数据集的状态。
- Redis 服务器会按照 AOF 文件中写操作的顺序,逐条执行这些操作,将数据集恢复到重启前的状态。
- AOF 文件的持久化:
- Redis 提供了不同的 AOF 持久化策略,可以通过配置文件设置:
appendfsync always
:每次写操作都会同步到 AOF 文件,这是最安全的方式,但也最慢。appendfsync everysec
:每秒同步一次,提供了很好的性能和持久性的折中。appendfsync no
:完全依赖于操作系统的 fsync。这种方式速度最快,但数据可能会有一定的丢失风险。
- Redis 提供了不同的 AOF 持久化策略,可以通过配置文件设置:
恢复机制对比
- RDB 恢复:由于 RDB 是一个快照文件,恢复速度相对较快,但是可能会丢失最后一次快照后的修改。
- AOF 恢复:AOF 通过重放操作日志来恢复数据,因此通常情况下能够保证数据更为完整,但可能会因为重放时间较长而导致恢复速度较慢。
选择 RDB 还是 AOF 作为持久化方式,通常取决于对数据完整性、恢复速度以及系统性能的不同要求。在生产环境中,通常会根据实际需求和配置选择合适的持久化方式或者两者结合使用。
欢迎交流
本文主要介绍什么是 AOF 重写,以及 AOF 重写的流程和原有低版本下 Redis 重写的弊端,以及高版本后升级的 Multi Part AOF,在文末还有三个问题,欢迎小伙伴在评论区留言,近期面试鸭小程序已全面上线,想要刷题的小伙伴可以积极参与!
1)AOF 重写的触发条件是什么?
2)AOF 重写如何实现压缩和优化?
3)AOF 重写的影响和性能考量是什么?