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