04 | 内存快照:宕机后, Redis 如何实现快速恢复
文章目錄
- 1. RDB內存快照的局限性
- 2. 給哪些內存數據做快照
- 3. 快照時數據能修改嗎
- 4. 可以每秒做一次快照嗎
- 4. 數據快速恢復
Redis 一另一種種持久化方法:內存快照。所謂內存快照,
是把某一時刻的狀態以文件的形式寫到磁盤上,這樣一來,即使宕機,快照文件也不會丟失,數據的可靠性也就得到了保證。這個快照文件就稱為 RDB 文件,其中,RDB 就是 Redis DataBase 的縮寫。
1. RDB內存快照的局限性
和 AOF 相比,RDB 記錄的是某一時刻的數據,并不是操作,所以,在做數據恢復時,我們可以直接把 RDB 文件讀入內存,很快地完成恢復。聽起來好像很不錯,但內存快照也并不是最優選項。為什么這么說呢?
我們還要考慮兩個關鍵問題:
- 對哪些數據做快照?這關系到快照的執行效率問題;
- 做快照時,數據還能被增刪改嗎?這關系到 Redis 是否被阻塞,能否同時正常處理請求。
2. 給哪些內存數據做快照
??Redis 的數據都在內存中,為了提供所有數據的可靠性保證,它執行的是全量快照,也就是說,把內存中的所有數據都記錄到磁盤中,這就類似于給 100 個人拍合影,把每一個人都拍進照片里。這樣做的好處是,一次性記錄了所有數據,一個都不少。
??RDB 文件的生成是否會阻塞主線程,這就關系到是否會降低 Redis 的性能。Redis 提供了兩個命令來生成 RDB 文件,分別是 save 和 bgsave。
- save:在主線程中執行,會導致阻塞;
- bgsave:創建一個子進程,專門用于寫入 RDB 文件,避免了主線程的阻塞,這也是Redis RDB 文件生成的默認配置。
3. 快照時數據能修改嗎
??在給別人拍照時,一旦對方動了,那么這張照片就拍糊了,我們就需要重拍,所以我們當然希望對方保持不動。對于內存快照而言,我們也不希望數據“動”。
??如果快照執行期間數據不能被修改,是會有潛在問題的。對于剛剛的例子來說,在做快照的 20s 時間里,如果這 4GB 的數據都不能被修改,Redis 就不能處理對這些數據的寫操作,那無疑就會給業務服務造成巨大的影響。
??你可能會想到,可以用 bgsave 避免阻塞啊。這里我就要說到一個常見的誤區了,避免阻塞和正常處理寫操作并不是一回事。此時,主線程的確沒有阻塞,可以正常接收請求,但是,為了保證快照完整性,它只能處理讀操作,因為不能修改正在執行快照的數據。
??為了快照而暫停寫操作,肯定是不能接受的。所以這個時候,Redis 就會借助操作系統提供的寫時復制技術(Copy-On-Write, COW),在執行快照的同時,正常處理寫操作。
??簡單來說,bgsave 子進程是由主線程 fork 生成的,可以共享主線程的所有內存數據。bgsave 子進程運行后,開始讀取主線程的內存數據,并把它們寫入 RDB 文件。此時,如果主線程對這些數據也都是讀操作(例如圖中的鍵值對 A),那么,主線程和bgsave 子進程相互不影響。但是,如果主線程要修改一塊數據(例如圖中的鍵值對 C),那么,這塊數據就會被復制一份,生成該數據的副本。然后,bgsave 子進程會把這個副本數據寫入 RDB 文件,而在這個過程中,主線程仍然可以直接修改原來的數據。
4. 可以每秒做一次快照嗎
??對于快照來說,所謂“連拍”就是指連續地做快照。這樣一來,快照的間隔時間變得很短,即使某一時刻發生宕機了,因為上一時刻快照剛執行,丟失的數據也不會太多。但是,這其中的快照間隔時間就很關鍵了。
??如下圖所示,我們先在 T0 時刻做了一次快照,然后又在 T0+t 時刻做了一次快照,在這期間,數據塊 5 和 9 被修改了。如果在 t 這段時間內,機器宕機了,那么,只能按照 T0 時刻的快照進行恢復。此時,數據塊 5 和 9 的修改值因為沒有快照記錄,就無法恢復了。
??在第一次做完全量快照后,T1 和 T2 時刻如果再做快照,我們只需要將被修改的數據寫入快照文件就行。但是,這么做的前提是,我們需要記住哪些數據被修改了。你可不要小瞧這個“記住”功能,它需要我們使用額外的元數據信息去記錄哪些數據被修改了,這會帶來額外的空間開銷問題。
如下圖所示:
4. 數據快速恢復
??一個混合使用 AOF 日志和內存快照的方法。簡單來說,內存快照以一定的頻率執行,在兩次快照之間,使用 AOF 日志記錄這期間的所有命令操作。這樣一來,快照不用很頻繁地執行,這就避免了頻繁 fork 對主線程的影響。而且,AOF日志也只用記錄兩次快照間的操作,也就是說,不需要記錄所有操作了,因此,就不會出現文件過大的情況了,也可以避免重寫開銷。如下圖所示,T1 和 T2 時刻的修改,用 AOF 日志記錄,等到第二次做全量快照時,就可以清空 AOF 日志,因為此時的修改都已經記錄到快照中了,恢復時就不再用日志了。
關于 AOF 和 RDB 的選擇問題,我想再給你提三點建議:
- 數據不能丟失時,內存快照和 AOF 的混合使用是一個很好的選擇;
- 如果允許分鐘級別的數據丟失,可以只使用 RDB;
- 如果只用 AOF,優先使用 everysec 的配置選項,因為它在可靠性和性能之間取了一個平衡。
總結
以上是生活随笔為你收集整理的04 | 内存快照:宕机后, Redis 如何实现快速恢复的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 03 | AOF 日志:宕机了, Red
- 下一篇: 11 | 脑裂: 一次奇怪的数据丢失