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

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