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工作全部结束。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章