首先我們知道AOF和RDB都是Redis持久化的方法。RDB是Redis DB,一種二進制數據格式,這樣就是相當于全量保存數據快照了。AOF則是保存命令,然后恢復的時候重放命令。
AOF隨著時間推移,會越來越大,因為不斷往里追加命令。所以需要重寫。重寫解決了什么呢?就是刪去了一些沒用的指令,比如有一條SET a 100,然后后面又有一條SET a 200,那前一條指令就是沒用的,只保留后面的即可。重寫就是重新生成AOF操作命令記錄的過程,還會順帶縮短重放時間。
AOF重寫流程
一處拷貝
fork一個子進程,和主進程共享Redis物理內存,把這些內存里的數據寫入新的AOF文件
兩處緩沖
重寫時候要是有新的寫入命令,主進程會把他們寫入到兩個緩沖里——AOF緩沖和AOF重寫緩沖。前者是為了給舊AOF文件,保證重寫過程宕機了也能根據舊的AOF文件恢復。后者是為了給新的AOF文件,重寫拷貝完內存區數據后將這部分增量數據一并寫入新AOF文件。
這里很多人都有一個誤區,重寫時候是根據舊AOF命令來的,實際上并不是!!!
AOF重寫觸發后,會fork一個子進程,子進程遍歷當前Redis DB中所有數據,然后再以字符串命令的形式寫入新AOF文件中。等這一步執行完了后,再將AOF重寫緩存區里的增量數據追加進新的AOF文件里。
全程沒有拷貝AOF緩存區,也和舊AOF文件沒關系!!!
混合持久化
這是對AOF重寫的一個優化(redis5之后的默認方式),即將當前的數據以RDB形式寫進新的AOF文件,追加的重寫緩沖區數據正常寫進新的AOF文件,二者共同構成新AOF文件來替代掉舊AOF文件。這樣有效降低了AOF文件的體積,并且從數據恢復角度上也變快了。
值得注意的是混合持久化仍然是AOF而非RDB和AOF雙開,數據恢復過程如下:
MP-AOF
MP-AOF是redis7提出來的,因為混合持久化還是有不足的,因為本質上還是沒解決一些問題。
不足
主進程要寫兩個緩沖,aof重寫緩沖和aof緩沖,這是兩個重復的操作,浪費CPU和內存。同時父進程在AOF重寫緩沖里的數據是通過管道傳遞給子進程的,然后子進程再將其追加寫入AOF,這也會造成CPU的額外開銷。兩個相同的緩沖的內容還得寫到新舊日志里,是額外的磁盤開銷(因為新日志替換舊日志前還是需要刷盤的)。
做法
全程Multi-Part AOF,就是將AOF拆分為Base AOF和Incr AOF了。Base AOF是fork子進程那一刻的RDB快照(redis5就默認開啟混合持久化了,redis7自然也是開啟了。假設關閉的話這里還是保存的命令)。Incr AOF是重寫過程中,主進程寫AOF緩沖區的指令。然后有一個Manifest文件,會記錄當前最新的Base AOF和Incr AOF是哪個文件,舊的會被標記然后異步刪除(UNLINK)。