redis aof rewrite流程

     aofrewrite是子进程完成的,在rewrite期间父进程处理客户端新到来的命令时,会将该命令缓存到server.aof_rewrite_buf_blocks中,并在命令追加的实现函数feedAppendOnlyFile最后一步将server.aof_rewrite_buf_blocks中的内容,通过管道发送给子进程。父子进程间通信的管道,总共有3个管道:

  1. 管道1用于父进程向子进程发送缓存的新数据。子进程在重写AOF时,定期从该管道中读取数据并缓存起来,并在最后将缓存的数据写入重写的AOF文件;
  2. 管道2负责子进程向父进程发送结束信号。由于父进程在不断的接收客户端命令,但是子进程不能无休止的等待父进程的数据,因此,子进程在遍历完数据库所有数据之后,从管道1中执行一段时间的读取操作后,就会向管道2中发送一个"!",父进程收到子进程的"!"后,就会置server.aof_stop_sending_diff为1,表示不再向子进程发送缓存的数据了;

  3. 管道3负责父进程向子进程发送应答信号。父进程收到子进程的"!"后,会通过该管道也向子进程应答一个"!",表示已收到了停止信号。

     

    aofrewrite子进程流程如下:

  1. 遍历内存中所有数据,每遍历10K数据后,就调用aofReadDiffFromParent,从管道中读取服务器(父进程)缓存的新数据,追加到    server.aof_child_diff中;
  2. 所有数据库的所有数据都重写完之后,先调用一次fflush和fsync操作,从而使aof文件内容确实写入磁盘。

  3. 再次调用aofReadDiffFromParent从父进程中读取累积的新数据,这里最多耗时1s的时间进行读取,并且如果有20次读取不到数据时,直接就停止该过程;

  4. 向管道中发送字符"!",以使父进程停止发送缓存的新数据;然后从管道中,尝试读取父进程的回应"!"。

  5. 最后一次调用aofReadDiffFromParent,读取管道中的剩余数据写入到aof中;然后调用fflush和fsync,保证aof文件内容确实写入磁盘。

  6. 将临时文件改名为filename,并返回REDIS_OK。注意,这里的参数filename,其实也是一个临时文件,其值为temp-rewriteaof-bg-<pid>.aof,子进程之所以将重写的AOF文件记录到临时文件中,是因为此时父进程还在向旧的AOF文件中追加命令。当子进程完成AOF重写之后,父进程就会进行收尾工作,用新的重写AOF文件,替换旧的AOF文件。

    父进程的收尾工作:

        父进程会在定时函数中serverCron()中会调用wait3()来等待子进程退出。子进程退出后,首先会打开子进程生成的新aof文件,并调用aofRewriteBufferWrite()把server.aof_rewrite_buf_blocks中剩余的数据追加到新aof文件。之后把新aof文件rename为server.aof_filename记录的文件名。至此aof rewrite工作全部结束。

### Redis AOF 重写的详细过程和原理 RedisAOF(Append Only File)持久化机制通过记录服务器执行的写命令来确保数据的安全性。然而,随着运行时间的增长,AOF 文件可能会变得非常庞大,导致加载时间过长,影响性能。为了解决这一问题,Redis 引入了 AOF 重写机制。 #### AOF 重写的触发条件 AOF 重写可以通过以下几种方式触发[^4]: - 手动执行 `BGREWRITEAOF` 命令。 - 主从复制完成后,无论 RDB 文件解析和加载是否成功。 - AOF 重写被设置为待调度执行。 - AOF 被启用,同时 AOF 文件的大小比例超出配置的阈值(如 `auto-aof-rewrite-min-size` 和 `auto-aof-rewrite-percentage`),并且 AOF 文件的绝对大小也超出设定的最小值。 #### AOF 重写的实现原理 AOF 重写的核心思想是生成一个新的、更紧凑的 AOF 文件,其中包含最少的写命令集合,能够重建当前的数据库状态。以下是其具体实现过程: 1. **Fork 子进程**:Redis 主进程通过 `fork` 系统调用创建一个子进程。子进程会继承父进程的内存页表,但由于写时复制(Copy-On-Write, COW)机制,父子进程在初始状态下共享同一份物理内存,只有当某个进程修改内存时才会分配新的页面[^1]。 2. **扫描内存数据**:子进程遍历 Redis 当前内存中的所有键值对,并将这些数据转换为一组高效的写命令。例如,如果某个列表包含多个元素,子进程不会逐条记录每个 `LPUSH` 或 `RPUSH` 操作,而是直接生成一个 `DEL` 和 `RPUSH` 的组合命令来表示整个列表的状态[^3]。 3. **生成新文件**:子进程将这些优化后的写命令写入到一个临时文件中(通常命名为 `temp-rewriteaof.aof`)。此过程完全由子进程完成,主进程可以继续处理客户端请求,从而避免阻塞。 4. **替换旧文件**:当子进程完成新 AOF 文件的生成后,它会通知父进程。父进程将旧的 AOF 文件原子性地替换为新的 AOF 文件,确保操作过程中不会丢失任何数据。 5. **同步写操作**:在子进程执行重写期间,主进程仍然会接收新的写命令。为了保证数据一致性,主进程会将这些命令同时追加到旧的 AOF 文件和一个缓冲区中。当重写完成后,缓冲区中的命令会被追加到新的 AOF 文件末尾,确保所有数据都被正确持久化[^3]。 #### AOF 重写的优点 - 减少 AOF 文件的体积,缩短加载时间,提高 Redis 的启动效率。 - 通过合并冗余命令,降低写入操作的复杂度,提升性能。 - 利用 COW 机制,最大限度地减少对主进程的影响,保持 Redis 的高可用性。 #### 示例代码 以下是一个简单的示例,展示如何手动触发 AOF 重写: ```bash # 使用 BGREWRITEAOF 命令触发 AOF 重写 redis-cli BGREWRITEAOF ``` #### 注意事项 - 配置参数 `auto-aof-rewrite-min-size` 和 `auto-aof-rewrite-percentage` 决定了自动触发 AOF 重写的条件。合理调整这些参数可以平衡性能和存储需求[^4]。 - 在高并发场景下,频繁的 AOF 重写可能会增加磁盘 I/O 压力,因此需要根据实际业务需求进行优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金士顿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值