Redis基礎篇(四)持久化:記憶體快照(RDB)

大雜草發表於2020-12-29

AOF好處是每次執行只需要記錄操作命令,記錄量不大。但在故障恢復時,需要逐一執行AOF的操作命令,如果日誌很大,恢復就很慢。

今天學習另一種持久化方式:記憶體快照。記憶體快照,是Redis某一時刻的狀態,以檔案的形式儲存在磁碟上。這個快照檔案就稱為RDB檔案,其中RDB就是Redis Database的縮寫。

當故障恢復時,只要把RDB檔案讀入記憶體即可,恢復速度很快。但是記憶體快照並不是最優選項,為什麼呢?

我們還需要考慮兩個問題:

  • 對哪些資料做快照?這關係到快照的執行效率;
  • 做快照時,資料還能被增刪改嗎?這關係到Redis是否被阻塞,能否同時正常處理請求。

對哪些資料做快照?

Redis的資料都在記憶體中,為了提供所有資料的可靠性保證,它執行的是全量快照。

Redis提供兩個命令生成RDB檔案:

  • save:在主執行緒中執行,但會導致阻塞;
  • bgsave:建立一個子程式,專門用於寫入RDB檔案,避免了主執行緒的阻塞。也是Redis RDB檔案生成的預設配置。

做快照時,資料還能被增刪改嗎?

如果快照執行期間資料不能被修改,是會有潛在問題的。假如做快照的20s時間裡,如果資料不能被修改,Redis就不能處理對這些資料的寫操作,那無疑就會給業務服務造成巨大影響。

Redis藉助作業系統提供的寫時複製技術(Copy-On-Write,COW),在執行快照的同時,正常處理寫操作。

bgsave流程圖

bgsave子程式是由主執行緒fork生成的,可以共享主執行緒的所有記憶體資料。

當主執行緒要修改資料時,通過COW複製一份副本出來給bgsave子程式。

這既保證快照的完整性,也允許主執行緒同時對資料進行修改,避免了對正常業務的影響。

可以每秒做一次快照嗎?

如果記憶體快照每隔幾分鐘執行一次,這樣就可能出現丟失資料的風險。那麼是否可以每秒做一次快照嗎?

如果頻繁地執行全量快照,會帶來兩方面開銷:

  • 一是頻繁將全量資料寫入磁碟,會給磁碟帶來很大壓力。
  • 二是bgsave子程式需要從主執行緒fork出來,fork建立過程本身會阻塞主執行緒,而且主執行緒的記憶體越大,阻塞時間越長。

既然頻繁執行全量快照不行,那還有什麼其他好方法嗎?

第一個方法是做增量快照

在第一次做完全量快照後,T1和T2時刻如果再做快照,只需要將被修改的資料寫入快照檔案就行了。如下圖所示:

image

第二個方法是Redis 4.0提出一個混合使用AOF日誌和RDB快照的方法:RDB快照以一定的頻率執行,在兩次快照之間,使用AOF日誌記錄這期間的所有命令操作。

T1和T2時刻的修改,用AOF日誌記錄,等到第二次做全量快照時,就可以清空AOF日誌,因為此時的修改都已經記錄到快照中了。如下圖所示:

image

擴充

使用一個2核CPU、4GB記憶體、500GB磁碟的雲主機執行Redis,Redis資料庫的資料量大小差不多是2GB,使用了RDB做持久化保證。當時Redis的執行負載以修改操作為主,寫讀比例差不多在8:2左右,也就是說,如果有100個請求,80個請求執行的是修改操作。在這個場景下,用RDB做持久化有什麼風險嗎?

主要有兩方面風險:記憶體資源風險CPU資源風險

記憶體資源風險

Redis fork子程式做RDB持久化,由於寫的比例為80%,那麼在持久化過程中,“寫時複製”會重新分配整個例項80%的記憶體副本,大約需要重新分配1.6GB記憶體空間,這樣整個系統的記憶體使用接近飽和。

如果此時父程式又有大量新key寫入,很快機器記憶體就會被吃光,如果機器開啟了Swap機制,那麼Redis會有一部分資料被換到磁碟上。

當Redis訪問這部分在磁碟上的資料時,效能會急劇下降,已經達不到高效能的標準。

如果沒有開啟Swap,會直接觸發OOM,父子程式會面臨被系統kill掉的風險。

CPU資源風險

雖然子程式在做RDB持久化,但生成RDB快照過程會消耗大量的CPU資源。

雖然Redis處理請求是單執行緒的,但Redis Server還有其他執行緒在後臺工作,例如AOF每秒刷盤、非同步關閉檔案描述符這些操作。

由於機器只有2核CPU,這也就是意味著父程式佔用了超過一半的CPU資源。

此時子程式做RDB持久化,可能會產生CPU競爭,導致的結果是父程式處理請求延遲增大,子程式生成RDB快照的時間也會變長,整個Redis Server效能下降。

如果Redis程式繫結了CPU,那麼子程式會繼續父程式的CPU親和性屬性,子程式必然會與父程式爭奪同一個CPU資源,整個Redis Server的效能必然會受到影響。

因此如果Redis需要開啟定時RDB和AOF重寫,程式一定不要繫結CPU。

參考資料

相關文章