對(duì)于快照來(lái)說,所謂“連拍”就是指連續(xù)地做快照。這樣一來(lái),快照的間隔時(shí)間變得很短,即使某一時(shí)刻發(fā)生宕機(jī)了,因?yàn)樯弦粫r(shí)刻快照剛執(zhí)行,丟失的數(shù)據(jù)也不會(huì)太多。但是,這其中的快照間隔時(shí)間就很關(guān)鍵了。
如下圖所示,我們先在 T0 時(shí)刻做了一次快照,然后又在 T0+t 時(shí)刻做了一次快照,在這期間,數(shù)據(jù)塊 5 和 9 被修改了。如果在 t 這段時(shí)間內(nèi),機(jī)器宕機(jī)了,那么,只能按照 T0 時(shí)刻的快照進(jìn)行恢復(fù)。此時(shí),數(shù)據(jù)塊 5 和 9 的修改值因?yàn)闆]有快照記錄,就無(wú)法恢復(fù)了。
所以,要想盡可能恢復(fù)數(shù)據(jù),t 值就要盡可能小,t 越小,就越像“連拍”。那么,t 值可以小到什么程度呢,比如說是不是可以每秒做一次快照?畢竟,每次快照都是由 bgsave 子進(jìn)程在后臺(tái)執(zhí)行,也不會(huì)阻塞主線程。
這種想法其實(shí)是錯(cuò)誤的。雖然 bgsave 執(zhí)行時(shí)不阻塞主線程,但是,如果頻繁地執(zhí)行全量快照,也會(huì)帶來(lái)兩方面的開銷:
一方面,頻繁將全量數(shù)據(jù)寫入磁盤,會(huì)給磁盤帶來(lái)很大壓力,多個(gè)快照競(jìng)爭(zhēng)有限的磁盤帶寬,前一個(gè)快照還沒有做完,后一個(gè)又開始做了,容易造成惡性循環(huán)。
另一方面,bgsave 子進(jìn)程需要通過 fork 操作從主線程創(chuàng)建出來(lái)。雖然,子進(jìn)程在創(chuàng)建后不會(huì)再阻塞主線程,但是,fork 這個(gè)創(chuàng)建過程本身會(huì)阻塞主線程,而且主線程的內(nèi)存越大,阻塞時(shí)間越長(zhǎng)。如果頻繁 fork 出 bgsave 子進(jìn)程,這就會(huì)頻繁阻塞主線程了。
那么,有什么其他好方法嗎?此時(shí),我們可以做增量快照,就是指做了一次全量快照后,后續(xù)的快照只對(duì)修改的數(shù)據(jù)進(jìn)行快照記錄,這樣可以避免每次全量快照的開銷。這個(gè)比較好理解。
但是它需要我們使用額外的元數(shù)據(jù)信息去記錄哪些數(shù)據(jù)被修改了,這會(huì)帶來(lái)額外的空間開銷問題。那么,還有什么方法既能利用 RDB 的快速恢復(fù),又能以較小的開銷做到盡量少丟數(shù)據(jù)呢?RDB和AOF的混合方式。