重寫 AOF 日志的過程是怎樣的?
Redis 的重寫 AOF 過程是由后臺子進程 bgrewriteaof 來完成的,這么做有以下兩個好處。
- 子進程進行 AOF 重寫期間,主進程可以繼續(xù)處理命令請求,從而避免阻塞主進程
- 子進程帶有主進程的數(shù)據(jù)副本。這里使用子進程而不是線程,是因為如果使用線程,多線程之間會共享內(nèi)存,那么在修改共享內(nèi)存數(shù)據(jù)的時候,需要通過加鎖來保證數(shù)據(jù)的安全,而這樣就會降低性能。而使用子進程,創(chuàng)建子進程時,父子進程是共享內(nèi)存數(shù)據(jù)的,不過這個共享的內(nèi)存只能以只讀的方式,而當父子進程任意一方修改了該共享內(nèi)存,就會發(fā)生「寫時復制」,于是父子進程就有了獨立的數(shù)據(jù)副本,就不用加鎖來保證數(shù)據(jù)安全
觸發(fā)重寫機制后,主進程就會創(chuàng)建重寫 AOF 的子進程,此時父子進程共享物理內(nèi)存,重寫子進程只會對這個內(nèi)存進行只讀,重寫 AOF 子進程會讀取數(shù)據(jù)庫里的所有數(shù)據(jù),并逐一把內(nèi)存數(shù)據(jù)的鍵值對轉(zhuǎn)換成一條命令,再將命令記錄到重寫日志(新的 AOF 文件)。
子進程是怎樣擁有和主進程一樣的數(shù)據(jù)副本的呢?
主進程在通過 fork 系統(tǒng)調(diào)用生成 bgrewriteaof 子進程時,操作系統(tǒng)會把主進程的「頁表」復制一份給子進程,這個頁表記錄著虛擬地址和物理地址映射關系,而不會復制物理內(nèi)存。簡單來說,兩者的虛擬空間不同,但其對應的物理空間是同一個。
這樣一來,子進程就共享了父進程的物理內(nèi)存數(shù)據(jù),這樣能夠節(jié)約物理內(nèi)存資源,頁表對應的頁表項的屬性會標記該物理內(nèi)存的權限為只讀。
不過,當父進程或者子進程在向這個內(nèi)存發(fā)起寫操作時,CPU 就會觸發(fā)寫保護中斷,這個寫保護中斷是由于違反權限導致的,然后操作系統(tǒng)會在「寫保護中斷處理函數(shù)」里進行物理內(nèi)存的復制,并重新設置其內(nèi)存映射關系,將父子進程的內(nèi)存讀寫權限設置為可讀寫,最后才會對內(nèi)存進行寫操作,這個過程被稱為「寫時復制」。
注意,這里只會復制主進程修改的物理內(nèi)存數(shù)據(jù),沒修改的物理內(nèi)存還是與子進程共享的。
但是在重寫過程中,主進程依然可以正常處理命令。那么問題來了,重寫 AOF 日志過程中,如果主進程修改了已經(jīng)存在的 key-value,就會觸發(fā)「寫時復制」,此時這個 key-value 數(shù)據(jù)在子進程的內(nèi)存數(shù)據(jù)就和在主進程的內(nèi)存數(shù)據(jù)不一致了。
為了解決這種數(shù)據(jù)不一致的問題,Redis 設置了一個 AOF 重寫緩沖區(qū),這個緩沖區(qū)在創(chuàng)建 bgrewriteaof 子進程之后開始使用。
在重寫 AOF 期間,當 Redis 執(zhí)行完一個寫命令之后,它會同時將這個寫命令寫入到 「AOF 緩沖區(qū)」和 「AOF 重寫緩沖區(qū)」。
也就是說,在 bgrewriteaof 子進程執(zhí)行 AOF 重寫期間,主進程需要執(zhí)行以下三個工作。
- 執(zhí)行客戶端發(fā)來的命令
- 將執(zhí)行后的寫命令追加到 「AOF 緩沖區(qū)」,用于后續(xù)通過 write() 系統(tǒng)調(diào)用,寫入內(nèi)核的緩沖區(qū),再由內(nèi)核決定在合適的時機將數(shù)據(jù)寫入磁盤
- 將執(zhí)行后的寫命令追加到 「AOF 重寫緩沖區(qū)」
當子進程完成 AOF 重寫工作(掃描數(shù)據(jù)庫中的所有數(shù)據(jù),逐一把內(nèi)存數(shù)據(jù)的鍵值對轉(zhuǎn)換成一條命令,再將命令記錄到重寫日志)后,會向主進程發(fā)送一條信號(信號是進程間通訊的一種方式,且是異步的)。
主進程收到該信號后,會調(diào)用一個信號處理函數(shù),該函數(shù)主要做以下工作。文章來源:http://www.zghlxwxcb.cn/news/detail-671514.html
- 將 AOF 重寫緩沖區(qū)中的所有內(nèi)容追加到新的 AOF 文件中,使得新舊兩個 AOF 文件所保存的數(shù)據(jù)狀態(tài)一致
- 對新的 AOF 的文件進行改名,覆蓋現(xiàn)有的 AOF 文件
信號函數(shù)執(zhí)行完后,主進程就可以繼續(xù)像往常一樣處理命令了。文章來源地址http://www.zghlxwxcb.cn/news/detail-671514.html
到了這里,關于Redis 重寫 AOF 日志期間,主進程可以正常處理命令嗎?的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!