1. 程式人生 > 實用技巧 >Redis設計與實現(十)AOF持久化

Redis設計與實現(十)AOF持久化

上個文章說到了RDB的持久化的過程以及RDB的檔案是如何進行儲存的。

和RDB不同的是,AOF的操作是通過把指令一個個儲存入檔案的,進行載入的時候就是一個個的command進行讀取,也就是模擬了一遍某時間段內的所有的操作。

由於Redis伺服器程序就是一個事件迴圈,這個迴圈中的檔案事件負責接受客戶端的命令請求,以及向客戶端傳送命令回覆,而時間事件則負責執行像ServerCron(100毫秒執行一次,check是否可以進行RDB的BGSAVE)一樣.伺服器可能在執行檔案事件的時候,進行一些寫的command,使得一些內容被追加到了aof_buf的緩衝區中去,所以AOF為了捕捉到這些被迫加入緩衝區的command會在處理檔案事件

結束後執行一個flushAppendOnlyFile的函式用來將aof_buf中的command加入到AOF檔案中去。

AOF持久化功能的實現可以分為:命令追加(append),檔案寫入(write),檔案同步(sync)三個步驟。

AOF持久化需要將所有寫命令記錄在檔案中來儲存伺服器狀態,而檔案寫入操作效率比較低,如果每執行一條寫命令都要寫一次AOF檔案無疑是低效的。為了提高效率,Redis提供了一箇中間層 – AOF緩衝區,也就是說當Redis執行一條寫命令後,先將該命令追加到AOF緩衝區中,在以後的某個時刻再將AOF緩衝區中的內容同步到檔案中。當AOF持久化功能處於開啟狀態時,伺服器在執行完一個寫命令之後,會以協議格式將被執行的寫命令追加到伺服器狀態的aof_buf緩衝區的末尾:

在載入AOF的時候

資料還原就是將AOF檔案中儲存的命令解析並執行,這樣就可以將資料庫還原為原來的狀態。因為在Redis中,命令必須由redisClient例項來執行,所以為了載入AOF檔案需要建立一個偽Redis客戶端。建立了偽Redis客戶端後,執行資料還原的過程就是從AOF檔案中讀取命令並交給偽Redis客戶端執行的過程。資料還原的功能由aof.c檔案中的loadAppendOnlyFile函式完成。

由於aof是通過不斷追加寫命令來記錄資料庫狀態,所以伺服器執行比較久之後,aof檔案中的內容會越來越多,磁碟佔有量越來越大,同時也是使通過過aof檔案還原資料庫的需要的時間也變得很久。所以就需要通過讀取伺服器當前的資料庫狀態來重寫新的aof檔案。新的AOF檔案不會包含任何浪費空間的冗餘命令,所以會比舊的AOF檔案小很多。

  由於AOF重寫是會進行大量寫入操作,勢必為長時間阻塞主程序,因此redis把重寫程式放到子程序執行。

這樣做有兩點好處

1)子程序重寫期間,主程序可以繼續處理命令。

2)子程序帶有主程序的資料副本,這樣就可以避免與主程序競爭db->dict,這是執行緒實現不了的。

  重寫期間,主程序繼續處理命令,對資料庫狀態進行修改,這樣使得當前的資料庫狀態與重寫的AOF檔案所儲存的資料庫狀態不一致。因此,redis設定了AOF重寫緩衝區,在建立子程序後,主程序每執行一個寫命令都會寫到重寫緩衝區。在子程序完成重寫後,主程序會將AOF重寫緩衝區的資料寫入到重寫的AOF檔案,保證資料狀態的一致。