AOF與RDB持久化經過保存數據庫中的鍵值對來記錄數據庫狀態不一樣,aof持久化是經過保存redis服務器所執行的寫命令來記錄數據庫狀態的。被寫入AOF文件的全部命令都是以Redis的命令請求協議格式保存的。redis
AOF持久化的實現能夠分爲命令追加(append),文件寫入,文件同步(sync)三個步驟。數據庫
當AOF持久化功能處於打開狀態,服務器在執行完一個寫命令以後,會以協議格式將被執行的寫命令追加到服務器狀態的aof_buf緩衝區末尾:bash
struct redisServer{ //... //AOF緩衝區 sds aof_buf //... };
例如 redis>SET KEY VALUE服務器
那麼服務器在執行這個set命令以後,會將如下協議內容追加到aof_buf緩衝區的末尾:網絡
*3\r\n$3\r\nSET\r\n$3\r\nKEY\r\n$5\r\nVALUE\r\napp
redis服務器進程就是一個事件循環(loop),這個循環中的文件事件負責接收客戶端的命令請求,以及向客戶端發送命令回覆,而時間事件則負責執行像serverCron函數這樣須要定時運行的函數。函數
由於服務器在處理文件事件時可能會執行寫命令,使得一些內容被追加到aof_buf緩衝區裏面,因此在服務器每次結束一個事件循環以前,它都會調用flushAppendOnlyFile函數,考慮是否須要將oop
aof_buf緩衝區的內容寫入和保存到AOF文件裏面。server
def eventLoop(): while true: //處理文件事件,接收命令請求以及發送命令回覆 //處理命令請求時可能會有新內容被追加到aof_buf緩衝區 processFileEvents() //處理時間事件 processTimeEvents() //考慮是否將aof_buf中的內容寫入和保存到AOF文件裏面 flushAppendOnlyFile()
flushAppendOnlyFile函數的行爲由服務器配置的appendfsync選項的值來決定,各個不一樣值產生的行爲以下表所示:blog
appendfsync默認值是everysec,能夠參考redis.conf配置文件
假設服務器在處理文件事件期間,執行了一些寫命令。若是這時flushAppendOnlyFile函數被調用,假設服務器當前的appendfsync的值是everysec,而且距離上次同步AOF文件已經超過1秒鐘,那麼服務器會先將aof_buf中的內容寫入到AOF文件中,而後再對AOF文件進行同步。
由於AOF文件裏面包含了重建數據庫狀態所需的全部寫命令,因此服務器只要讀入並從新執行一遍AOF文件裏面保存的寫命令,就能夠還原服務器關閉以前的數據庫狀態。
redis讀取AOF文件並還原數據的具體步驟以下:
1)建立一個不帶網絡鏈接的僞客戶端:由於redis的命令只能在客戶端上下文中執行,而載入aof文件時所使用的命令直接來源於AOF文件而不是網絡鏈接,因此服務器使用僞客戶端來執行aof文件保存的寫命令,僞客戶端執行命令的效果和帶網絡鏈接客戶端執行命令的效果徹底同樣。
2)從AOF文件中分析並讀取一條寫命令
3)使用僞客戶端執行被讀出的寫命令
4)一直執行步驟2和步驟3,知道文件讀取完畢
其實就是爲了解決AOF文件體積膨脹的問題,Redis提供了AOF文件重寫功能。
aof重寫程序是放在子進程裏執行的