MongoDB 產品上線前隱藏殺手

對 Oplog 不熟的朋友,建議先閱讀之前的內容


四年一度的大型盛事終於結束,來回顧一下這個我們都知道,卻隱藏得很好的 MongoDB 殺手 - Oplog。


在流量真正進入之前,我們進行了多次的功能驗證、壓力測試,確保在各個環節都沒有問題,對於各個服務的狀態也甚是滿意。展開了 MongoDB Atlas 監控,正式迎接挑戰!

剛開始我們很明顯感受到流量帶來的壓力,各項數據都還是穩定、可預期的,這時候是第一個錯誤。

等到第二天、第三天,我們開始發現 Oplog 的 headroom 開始有降低趨勢,這部分根 Oplog GB/Per hour 是呈現相反的,畢竟量多了,自然餘裕就開始減少。

第一個錯誤是沒有仔細評估合理性,對於流量的增長,到底多少是合理的呢?這個在事情必須要充足的測試才有辦法進行推斷。

這個問題也衍伸出另一件事,就是全服務的壓力測試非常重要,在 pre-production 環境應該事先給予充足的壓力測試。

展開調查

我馬上在次一個環境展開調查,查看 oplog 這個 collection 裡面的資料分布,日後應該能夠寫個 script 進行分析哪類型的 數量 與 size 佔比,畢竟 oplog 數量與大小是影響抄寫速度的關鍵。

第二個錯誤發生在此,確認好哪些部分可以降低觸發頻率以減輕 oplog 負擔後,修改就一路上到 PROD 環境,再等待一兩天後,仍然不見顯著好轉跡象。最大原因在於次一個環境(我們是 UAT),客戶與使用者的操作行為與流量大不相同,因此這個分析不能完全反映真實情況。

礙於範圍大的查詢對 PROD 可能是一個潛在負擔,我們決議不這麼做。

在這個非常時刻,除非有嚴重錯誤,否則也不適合對流程上有大幅度的修改。既然程式面與分析都不是用,最後選擇了最快速的做法:升級機器與調整 Oplog size。

首先是調整 Oplog collection size,要說明一下這個做法就是用空間換取時間,因為 oplog 抄寫量完全趕不及產出量,因此時間拉長了還是會有空間不足的情況產生,不過這個改動很適合我們緊急止血,至少買到一些時間,撐過巨大衝擊的期間即可。

再來是升級 MongoDB 規格,使用 Atlas 的服務就是這麼方便,升級過程中幾乎是無痛執行,我們選定了一個離峰時刻執行,順便調整 oplog size,最後終於把 headroom 慢慢往上拉高,使得 oplog 不會空間不足。


Conclusion

  1. 開發期間,我們應該仔細檢驗 oplog 的大小與數量是否合理,而非只關注功能是否完成
  2. oplog 基礎的抄寫資訊大約是 0.8 kb,再加上抄寫的資料內容可以估算出一個 document 大小
  3. 使用 Update 而非 Replace
  4. 儲存的資料結構是否可以更精簡
  5. 週期性執行的任務,確保在離峰時間執行,以免搶佔尖峰時間的資源
  6. TTL index 可以在特定期間移除,例如預期有兩週的尖峰時刻,那可以把那兩週的 TTL 資料預先延長到尖峰時刻之後,因為 DELETE 也是會產生 oplog。
  7. 商務流程上,能夠合併更新資料庫的,就應該從流程上或架構面著手,避免無謂的資料更新。例如要確保某一個資料有按時更新,即便沒內容我們也會去更新 Last Update Time 欄位。
  8. 預設 oplog collection size 就是 disk 的 5% 空間,這個是可以預先調大的,畢竟單獨修改這個項目會需要資料庫的重啟。
  9. 上線前給予系統面足夠大的壓力測試,且這個壓力測試要持續一段時間,這樣觀測 oplog headroom 才夠精準。
  10. 透過壓力測試再度分析 oplog 大小與數量是否符合預期
  11. 花錢了,直接升級 Atlas,各項硬體規格的提升,直接使 oplog 抄寫更快。

oplog 的概念不難,但卻是非常容易被忽略的一個項目。

在我上面遇到的例子就是緊要關頭,能選擇的解決方案已經剩下升級,希望大家不要遇到XD

  • 作者: MingYi Chou
  • 版權聲明: 轉載不用問,但請註明出處!本網誌均採用 BY-NC-SA 許可協議。