2024年1月25日 星期四

MongoDB Atlas Auto-Scaling的神奇事

最近工作負責了改善產品系統使用Mongo DB的效能部分, 最主要做了把部分大流量的操作從Synchronous改成Asynchronous, 以及針對一些DB的寫入操作做Cache壓縮, 把一些暫態的寫入操作放到Cache keep住, 等Cache滿了或Schedule Timer時間到了在自動刷新Cache & 寫入到DB, 節省不必要的DB寫入。

改善完以後觀察Mongo Atlas Metrics, IOPS, CPU, Network, DB Update都降了不少, 可是唯獨Memory的使用量卻幾乎沒變, 用量一直維持在50%~60%左右, 而且不管是尖峰或離峰的情況都一直維持一個很平穩的狀態。

常理想應該是Mongo Atlas的DB Server在啟動時有預留一些記憶體當Cache使用, 所以照理說也不是什麼大問題。會覺得奇怪的地方是, 因為我們使用了Mongo Atlas Auto-Scaling服務, 在改善效能之前我們的DB Cluster Tier是M40, 這次改善的部分還不小, 對比過去的資料應該M30就夠用了, 為什麼沒有觸發Auto Scaling Down到M30呢?


後來就去查了一下Mongo Atlas的文件, 關於Auto-Scaling的文件可以參考這裡:

https://www.mongodb.com/docs/atlas/cluster-autoscaling/

其中關於Auto-Scaling的條件如下:



Scaling Up的條件是過去一小時內CPU or Memory > 75%; 而Scaling Down的條件則是過去24小時CPU and Memory < 50%, 看條件其實蠻合理的, 畢竟會需要Scaling Up的時候通常是系統忽然遇到高流量的情況, 不趕緊Scaling Up可能就要被打爆了; 而Scaling Down就比較寬鬆, 畢竟反反覆覆Scaling對系統也不太好, 系統穩定性相對Cost重要得多。


看上面的條件可以發現是因為M40的System Memory使用率一直都高於50%, 所以才無法觸發Auto Scaling Down, 可是我觀察過去系統在M30的Metrics, 發現記憶體用量卻是一直低於50%, 反而是Scaling Up到M40的瞬間就一直大於50%了, 相同流量下規格較差的DB Clusters反而記憶體整體用量比較小也太奇怪。


後來去查了下Mongo關於Atlas Cluster Sizing and Tier Selection的文件:

https://www.mongodb.com/docs/atlas/sizing-tier-selection/


M40或更高規格的Clusters, 會預設把50%的實體記憶體給WiredTiger Cache使用, M30或更低規格的Clusters則是預設把25%實體記憶體給WiredTiger用。 這也是為什麼會觀察到低規格的Clusters記憶體整體用量會比高規格小的關係。


然後問題就來了, 我要Auto Scaling Down就必須過去24小時CPU and Memory < 50%, 可是M40以上的Clusters又預設給WiredTiger 50%的實體記憶體, 這樣我這Auto Scaling Down的機制還能work嗎XD  後來就乾脆把上述的finding以及過去兩年Scaling Event整理一下, 敲Support Ticket Case請Mongo的人幫忙解答, Mongo Support的回覆如下:

for M40 or larger clusters, WiredTiger dedicates more than 50% of RAM - 1 GB for the WiredTiger cache in Atlas. Out which Atlas always tries to maintain 80% of the total allocated WiredTiger cache for performance optimisation. The main goal of WiredTiger cache is to avoid I/O operations to load the page from the disk while not reaching a fill ratio of over 80%. If the working set is bigger than the cache, the goal is to perform as few evictions as possible. Our internal article on How does MongoDB use memory? will provide you more insights.

...

Our product team is aware of the issues with auto downscaling based on memory utilisation for M40+ tier and they are working internally to improve this.


WiredTiger Storage Engine的文件中Memory Use的段落也有提到WiredTiger使用的預設記憶體大小:
https://www.mongodb.com/docs/manual/core/wiredtiger/


因為WiredTiger預設會吃50% - 1GB的實體記憶體, 所以只要M40 Clusters使用的記憶體扣掉WiredTiger超過1GB, 那就很難有機會Trigger到Auto Scaling Down, 尤其是對越高規格的Clusters來說更是如此。 而關於這問題Mongo Support也有回覆他們有注意到Auto Scaling Down在M40+會有這問題, 內部正在研究怎麼改善它, 而在Mongo改善這問題之前, 如果你遇到偶發的高流量事件或是寫出某個Bug導致Auto Scaling Up, 又或者你最近有Enhance Performance而且改善後目前的Cluster Tier太高的話, 可能就得自己手動降低Spec, 避免多花無謂的$$。


這次的分享大概就到這邊, 好久沒寫開發雜談了, 雖然工作上總會遇到各種神奇事, 不過會想要分享寫到部落格的卻很少, 畢竟寫部落格文章還蠻花時間的, 只想寫些印象深刻的事件並記錄下來XD