Redis-AOF日誌與RDB快照

rookie丶發表於2021-04-10

  AOF日誌與RDB是Reids中兩大持久化機制,當伺服器或者Reids當機的時候可以通過這兩大機制恢復Redis的資料。

  先說說AOF日誌吧,在執行一條操作請求時,Redis先將命令在記憶體中執行,之後再將命令寫到AOF日誌中,與我們熟悉的MySQL的redo log日誌先寫日誌再執行sql的順序剛好相反。

  這麼做的好處主要有兩點:

    • 先執行命令再寫入AOF日誌確保命令不存在語法錯誤能正常的被執行;
    • 不阻塞主執行緒;

  在Redis中AOF日誌有三種寫回的策略:

    • Always,同步寫回。執行完命令立即寫入AOF檔案;
    • Everysec,每秒寫回。執行完命令後將命令寫入緩衝區,每秒將緩衝區命令寫入AOF檔案;
    • No,由作業系統寫回。執行完命令後將命令寫入緩衝區,由作業系統決定何時將緩衝區命令寫入AOF檔案;

  

  由於持續不斷的操作Redis服務,這時AOF日誌檔案的將持續變大,將會帶來一些效能上的問題:

    • 系統無法儲存過大的檔案;
    • AOF檔案過大時將會影響命令寫入的效率;
    • 如果發生當機,AOF檔案過大會導致資料恢復變得緩慢;

  針對AOF檔案過大問題Redis採用重寫AOF檔案的方式來避免AOF檔案過大帶來的效能問題。與AOF日誌由主執行緒寫入的方式不同,AOF重寫由後臺子執行緒bgrewriteaof 來完成的,這也是為了避免阻塞主執行緒,導致資料庫效能下降。

  重寫的過程主要體現在兩個方面:一個拷貝,兩處日誌。

  Redis中通過auto-aof-rewrite-min-size、auto-aof-rewrite-percentage來判斷是否觸發重寫機制,當AOF檔案大小同時超出這兩個引數設定的值後就會觸發AOF重寫。

  當觸發AOF重寫後,主執行緒會fork一個子執行緒bgrewriteaof ,同時將複製一份主執行緒的頁表(一個拷貝)給子執行緒,這樣子執行緒就能訪問到記憶體中的資料了,在不影響主執行緒的情況下逐一將資料轉成命令記錄重寫日誌。

  在AOF日誌重寫過程中,當有新的操作命令的時候,Redis會將命令寫入AOF緩衝區的同時也會寫入重寫AOF的緩衝區(兩處日誌),當重寫完成後,重寫緩衝區的命令會寫入新的AOF檔案中。此時,新的AOF檔案就可以代替舊的AOF檔案了。

  

  你可能會疑惑為什麼重寫後的AOF檔案會比較小呢?

  因為舊的AOF檔案記錄著每一條操作命令,可能存在多條命令執行同一個資料的情況,而AOF重寫是將記憶體中的資料轉成命令儲存這樣一條資料就只會存在一條命令,從而達到縮小AOF檔案檔案大小的目的。

  與AOF日誌相比RDB快照的邏輯就相對簡單一些。

  RDB快照可以理解為Redis資料的全量備份,Redis通過兩個命令來生成RDB檔案:

    • save:在主執行緒中執行,會阻塞主執行緒;
    • bgsave:建立一個子執行緒去寫入RDB檔案,避免了主執行緒阻塞,Redis預設配置;

  首先在Redis主執行緒會fork一個子執行緒bgsave,同時複製一份主執行緒頁表給bgsave,這樣bgsave子執行緒就能讀到主執行緒的記憶體中的資料了將其寫到RDB快照中,所以不會影響主執行緒的讀操作。

  但是,如果是一個操作請求這時Redis為了保證正常操作請求會藉助系統的寫時複製技術(Copy-On-Write, COW),當有操作請求時,主執行緒會申請一份新的記憶體空間存放資料同時修改自己的頁表對映。

  這樣既保證了快照的完整性,也保證了主執行緒的正常操作。

  在Redis4.0後提出了混合使用AOF和RDB快照的方法,先通過全量備份Redis資料的RDB快照,之後通過AOF日誌檔案做增量備份。

  

 

相關文章