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