更新時間:2022-11-14 來源:黑馬程序員 瀏覽量:
為什么需要AOF 重寫?
AOF 會記錄每個寫命令到 AOF 文件,隨著時間越來越長,AOF 文件會變得越來越大。如果不加以控制,會對 Redis 服務(wù)器,甚至對操作系統(tǒng)造成影響,而且 AOF 文件越大,數(shù)據(jù)恢復(fù)也越慢。為了解決 AOF 文件體積膨脹的問題,Redis 提供 AOF 文件重寫機制來對 AOF 文件進行 “瘦身”。
Redis 通過創(chuàng)建一個新的 AOF 文件來替換現(xiàn)有的 AOF,新舊兩個 AOF 文件保存的數(shù)據(jù)相同,但新 AOF 文件沒有了冗余命令。
AOF 重寫會阻塞嗎?
AOF 重寫過程是由后臺進程 bgrewriteaof 來完成的。主線程 fork 出后臺的 bgrewriteaof 子進程,fork 會把主線程的內(nèi)存拷貝一份給 bgrewriteaof 子進程,這里面就包含了數(shù)據(jù)庫的最新數(shù)據(jù)。然后,bgrewriteaof 子進程就可以在不影響主線程的情況下,逐一把拷貝的數(shù)據(jù)寫成操作,記入重寫日志。
所以 AOF 在重寫時,在 fork 進程時是會阻塞住主線程的。
AOF 日志何時會重寫?
有兩個配置項控制 AOF 重寫的觸發(fā):
auto-aof-rewrite-min-size: 表示運行 AOF 重寫時文件的最小大小,默認(rèn)為 64MB。
auto-aof-rewrite-percentage: 這個值的計算方式是,當(dāng)前 AOF文件大小和上一次重寫后 AOF
文件大小的差值,再除以上一次重寫后 AOF 文件大小。也就是當(dāng)前 AOF 文件比上一次重寫后 AOF 文件的增量大小,和上一次重寫后 AOF
文件大小的比值。
重寫日志時,有新數(shù)據(jù)寫入,主進程是怎么做的?
重寫過程總結(jié)為:“一個拷貝,兩處日志”。在 fork 出子進程時的拷貝,以及在重寫時,如果有新數(shù)據(jù)寫入,主線程就會將命令記錄到兩個 aof 日志內(nèi)存緩沖區(qū)中。如果 AOF 同步策略配置的是 always,則直接將命令寫回 舊的日志文件 ,并且保存一份命令至 AOF重寫緩沖區(qū) ,這些操作對新的日志文件是不存在影響的。(舊的日志文件:主線程使用的日志文件,新的日志文件:bgrewriteaof 進程使用的日志文件)
而在 bgrewriteaof 子進程完成會日志文件的重寫操作后,會提示主線程已經(jīng)完成重寫操作,主線程會將 AOF 重寫緩沖中的命令追加到新的日志文件后面。這時候在高并發(fā)的情況下,AOF 重寫緩沖區(qū)積累可能會很大,這樣就會造成阻塞,Redis 后來通過 Linux 管道技術(shù)讓 aof 重寫期間就能同時進行回放,這樣 aof 重寫結(jié)束后只需回放少量剩余的數(shù)據(jù)即可。
最后通過修改文件名的方式,保證文件切換的原子性。
在 AOF 重寫日志期間發(fā)生宕機的話,因為日志文件還沒切換,所以恢復(fù)數(shù)據(jù)時,用的還是舊的日志文件。
在重寫日志整個過程時,主線程有哪些地方會被阻塞?
1、fork 子進程時,需要拷貝虛擬頁表,會對主線程阻塞 。
2、主進程有 bigkey 寫入時,操作系統(tǒng)會創(chuàng)建頁面的副本,并拷貝原有的數(shù)據(jù),會對主線程阻塞。
3、子進程重寫日志完成后,主進程追加 aof 重寫緩沖區(qū)時可能會對主線程阻塞