《Redis设计与实现》之第十一章:AOF持久化
AOF持久化是通過保存Redis服務器所執行的寫命令來記錄數據庫狀態的。被寫入AOF文件的所有命令都是以Redis的命令請求協議格式(純文本)保存的。
一,AOF持久化的實現
1.命令追加
當AOF持久化功能處于打開狀態時,服務器在執行完一個寫命令后,會以協議格式把被執行的寫命令追加到服務器狀態的aof_buf緩沖區的末尾:
struct redisServer{
//AOF緩沖區
sds aof_buf;
}
2.AOF文件的寫入和同步
命令請求會先保存到AOF緩沖區中,然后在寫入并同步到AOF文件。
Redis服務器進程是一個事件循環,在這個循環中有文件事件,有時間事件。文件事件負責接收客戶端的命令請求和向客戶端發送命令回復。時間事件負責執行定時運行的函數,比如:serverCron函數。
偽代碼:
def eventLoop():
while true:
//處理文件事件,接收命令請求以及發送命令回復。處理命令請求時可能會有新內容被追加到aof_buf緩沖區中
processFileEvents()
//處理時間事件
processTimeEvents()
//考慮是否要把 aof_buf中的內容寫入和保存到AOF文件中
flushAppendOnlyFile()
?
寫入:在現代操作系統中,當數據寫入到文件中時,會調用write函數。操作系統會將寫入數據暫時保存在一個內存緩存區中,等到緩沖區空間滿的時候,才真正將緩沖區中的數據寫入到磁盤中。
同步:同時系統也提供了同步函數,它可以強制讓操作系統立即將緩沖區中的數據寫入到磁盤中。
?
由上面的代碼可以知道,在每個事件循環都會調用flushAppendOnlyFile函數,flushAppendOnlyFile函數的行為由appendfsync的值決定:
always:服務器在每個事件循環都要將aof_buf緩沖區中的所有內容寫入到AOF文件中,并同步AOF文件(寫入并同步)(,把aof_buf數據寫入并同步到AOF文件中)
everysec:服務器在每個事件循環都要將aof_buf緩沖區中的所有內容寫入到AOF文件中(先寫入),并且每隔一秒就在子線程中對AOF文件進行一次同步(每隔一秒同步)。
no:服務器在每個事件循環都要將aof_buf緩沖區中的所有內容寫入到AOF文件中(先寫入),至于什么時候同步,由操作系統控制(不知道啥時候同步)。在該模式下的flushAppendOnlyFile的調用不需要同步執行。
?
二,AOF文件的載入和數據還原
1.數據還原:AOF文件中包含了重建數據庫狀態的所有寫命令,所以服務器只要讀入并重新執行一遍AOF文件里保存的寫命令,就可以還原數據
2.步驟:
創建一個不帶網絡連接的偽客戶端。(為什么是為客戶端:Redis的命令只能在客戶端上下文中執行,為什么是不帶網絡連接:命令來自AOF文件而不是網絡連接)
從AOF文件中分析并讀取一條寫命令
使用偽客戶端執行被讀出的寫命令
一直執行步驟2,3 。直到AOF文件中的所有寫命令都被處理完畢
?
三,AOF重寫
1.什么是AOF重寫?
為了解決AOF文件體積膨脹,Redis服務器創建一個新的AOF文件替代現有的AOF文件,新舊兩個文件保存的數據庫狀態相同,但是新AOF文件不會包含冗余命令。
Redis把新AOF文件替換舊AOF文件的功能叫 AOF文件重寫。
2.AOF文件重寫的實現
注意:AOF文件重寫并不需要對現有的AOF文件進行如何讀取,分析或寫入操作,這個功能是通過讀取服務器當前的數據庫狀態來實現的。
原理:首先從數據庫中讀取鍵現在的值,然后用一條命令記錄鍵值對,代替之前記錄這個鍵值對的多條命令。
【如果服務器想要用盡量少的命令來記錄鍵的狀態,那么最簡單的辦法不是去讀取和分析現有AOF文件的內容,而是直接從數據庫中讀取鍵的值,然后用一條寫命令來替代保存在AOF文件中的多條寫命令,這樣就可以把保存鍵的多條命令減少為一條。】
在實際中,為了避免在執行命令時造成客戶端輸入緩沖區溢出。在處理有多個元素的鍵時,會先檢查鍵包含的元素數量,如果超過了一定的值,會使用多條命令來記錄鍵的值。比如一個列表鍵包含了超過64個項,那么重寫程序會用多條rpush命令來保存這個列表。
3.AOF后臺重寫
問題:由于Redis服務器使用單個線程處理命令請求,當服務器調用aof_rewrite函數時,在重寫AOF文件期間,服務器無法處理客戶端發送來的命令請求
解決:把AOF重寫程序放到子進程中執行,這樣子進程重寫期間,父進程可以繼續處理命令請求。并且子進程帶有父進程的數據副本。
那么問題又來了:在子進程進行AOF重寫期間,服務器進程在處理命令請求時可能會改變數據庫狀態,導致服務器當前數據庫狀態和重寫后的AOF文件保存的數據庫狀態不一致
為了解決數據不一致問題,Redis服務器設置了一個AOF重寫緩沖區,這個緩沖區在創建子進程之后使用,當Redis服務器執行完一個寫命令后,會同時把這個寫命令發送給AOF緩沖區和AOF重寫緩沖區。
在子進程執行AOF重寫期間,服務器需要:
執行客戶端發送過來的命令
將執行后的寫命令追加到AOF緩沖區
將執行后的寫命令追擊到AOF重寫緩沖區
當子進程完成重寫工作后,向父進程發送一個信號,父進程在接到這個信號后,把AOF重寫緩沖區中的所有內容寫到新AOF文件中,并對新的AOF文件進行改名,覆蓋現有的AOF文件。
?
轉載于:https://www.cnblogs.com/inspred/p/10676708.html
總結
以上是生活随笔為你收集整理的《Redis设计与实现》之第十一章:AOF持久化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 修改时区为上海
- 下一篇: Java新手如何学习Spring、Str