Redis AOF持久化

Redis提供了AOF(Append Only File)持久化功能,AOF通過保存服務器所執行命令來記錄數據庫狀態的,和MySQL記錄增刪改的log有點像哈。


AOF持久化功能實現分爲命令追加(append)、文件寫入(write)和文件同步(sync)三個步驟。


1.AOF命令追加

當開啓AOF持久化功能時,服務器會在執行完一個寫命令後,會以協議格式將執行的寫命令追加到服務器狀態的aof_buf緩衝區末尾。


2.AOF文件寫入和同步

Redis服務進程就是一個事件循環,循環中的文件事件負責接受客戶端的命令請求,以及向客戶端發送命令回覆,而時間事件則負責執行像serverCron函數這樣需要定時運行的函數。

def eventLoop():

while True:

#處理文件事件,接收命令以及發送命令

#處理命令時可能會有新內容被追加到aof_buf中

processFileEvents()

#處理時間事件

processTimeEvents()

#考慮是否將aof_buf中內容寫入和保存到aof文件

flushAppendOnlyFile()


flushAppendOnlyFile函數的行爲由服務器配置的appendfsync選項值來決定。

appendfsync配置:

always : 服務器在每個事件循環都要將aof_buf緩衝區的所有內容寫到AOF文件,並同步,效率最慢,但最安全。

everysec : 服務器在每個事件循環都將aof_bug緩衝區的所有文件寫到AOF文件,並且每隔1s就在子線程中對AOF文件做同步,效率快。

no : 服務器在每個事件循環都將aof_bug緩衝區的所有文件寫到AOF文件,此模式下的flushAppendOnlyFile無須執行同步操作,同步AOF文件由操作系統決定,寫入速度最快。


3.AOF重寫

隨着服務器運行時間的流逝,AOF文件中的內容會越來越多,可能會對Redis服務器和宿主計算機造成影響。

雖然Redis將生成新AOF文件替換舊AOF文件功能命名爲AOF文件重寫,但實際上,AOF文件重寫並不需要對現有AOF文件進行任何讀取、分析和寫入操作,這個功能是通過讀取服務器當前數據庫狀態來實現的。

實際操作中,Redis依次遍歷數據庫中所有key,並根據key類型的不同,取出相應值並生成對應類型的寫入語句。同時,爲了避免在執行命令時造成客戶端輸入緩衝區溢出,重寫程序在處理列表、哈希表、集合、有序集合這4種可能會帶有多個元素的鍵時,會先檢查鍵所包含元素的數量,如果數量超過了redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD常量的值,那重寫程序會使用多條命令來記錄鍵的值。當前版本中,REDIS_AOF_REWRITE_ITEMS_PER_CMD常量值爲64,所以每條語句最多會寫入64個元素。


4.AOF後臺重寫

上面介紹的AOF重寫可以很好的完成創建一個新AOF文件的任務,但是,這個操作會進行大量的寫入操作,所以調用這個函數的線程將被長時間阻塞,因爲Redis服務器使用單個線程來處理命令請求,所以如果由服務器調用AOF重寫,那麼在重寫期間,服務器將無法處理客戶端發來的請求。

Redis並不希望AOF的重寫操作造成服務器無法處理請求,所以需要將重寫放到子進程裏執行,這樣做可以達到兩個目的:

1)子進程執行AOF重寫期間,服務器可以繼續處理客戶端的命令請求。

2)子進程帶有服務器進程的數據副本,使用子進程而不是線程,可以在避免使用鎖的情況下,保證數據安全性。


不過這裏仍然存在一個問題:在子進程執行AOF重寫期間,服務器處理客戶端的命令請求時,對現有數據庫狀態進行修改操作,會使得服務器當前數據庫狀態和重寫後的AOF文件所保存的數據庫狀態不一致。

爲了解決這個問題,Redis服務器設置了一個AOF重寫緩衝區,這個緩衝區在服務器創建子進程之後開始使用,當Redis執行完一個寫命令後,它會同時將這個寫命令發送給AOF緩衝區和AOF重寫緩衝區。

以上就是AOF後臺重寫,即BGREWRITEAOF命令的實現原理。






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