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