1. 程式人生 > >MongoDB 效能瓶頸分析

MongoDB 效能瓶頸分析

一、前情簡介

半個月前,公司的MongoDB壓力由於使用者量暴增導致壓力急劇增加,讀寫能力下降。 
因為對於Mongos 的叢集分片機制的瞭解和測試還不是很充分,所以開始使用最簡單的辦法來解決:提高配置。 
眾所周知,MongoDB是出了名的吃記憶體。當時定義出來提高MongoDB的辦法很簡單,插記憶體。 
但是由於機房問題,插記憶體需要拔電源,導致停止產品的服務,所以經過研究後。 
用我們備用的R710 64GB記憶體伺服器來替代線上的R410 32GB記憶體的伺服器。 

二、操作方式

(1)首先是確認防火牆,埠是否開放,MongoDB1.82升級2.02安裝成功,所有操作在內網進行。 
(2)使用Rsync將R410伺服器的MongoDB主庫資料
同步到R710中。 
同步結束之後,刪除R710本地Local檔案。以從庫模式啟動,開始同步R410中MongoDB主庫的資料。 
在同步延時在1s左右。確認資料及時同步。 
(3)在確認資料同步後,切斷所有資料庫Write操作的入口。使MongoDB主庫的資料不再出現變動。 
這之後確認從庫的資料已經與主庫完全同步。進入主庫,shutDownServer()。停止主庫服務。 
然後進入從庫,shutDownServer。停止從庫服務。 
然後再將R710中的從庫以主庫的模式重新啟動。這時同時切換所有訪問資料庫程式的Hosts。使其從R410的主機IP指向到R710的主機IP。這時啟動所有服務。 

三、啟動後的驚心動魄


啟動服務之後,MongoDB並沒有像我們想象中的瘋狂的佔用記憶體,起初只是佔用了2.5G左右的記憶體。 
使用者在頻繁的訪問資料庫,通過MongoStat觀察到。使用者的QR和QW也就是讀寫佇列不停堆積。Locked值居高不下。 
明顯是處理不過來。建立的conn連線數越來越多,導致客戶端頻繁的出發TimeOut。 
最後甚至引起了MongoDB鎖死,不再執行任何操作。寫入佇列堆積到20000+。 
之後進行查詢,網上說MongoDB2.02 + R710需要在啟動引數中追加numactl --interleave=all 。
經過新增後,鬆了一口氣,因為無效。 
之後的幾天頻繁出現問題,MongoDB佔用記憶體最高只打到5GB的熱點資料。 

在昨天中午資料庫徹底鎖死宕機。 
問題被定位在R710的硬體裝置不相容上。 
被迫在白天的時候重新操作了一次之前的工作,將資料庫遷移回R410。 
在晚上的時候進行觀測,發現資料依然不夠理想。還是一樣的效果。 
之後開始懷疑是因為MongoDB1.82升級到2.02導致的問題,開始查閱資料。但是依然毫無進展。 

四、一些效能優化

之後進行Nginx和MongoDB的log觀察。發現每分鐘大概14000的動態請求。而MongoDB的log一直在展示一些可怕的慢查詢,最長的一次竟然有370秒! 
MonogoDB有個很坑爹的地方就Auth驗證,我之前的日誌還描述過這個東西,但是沒想到每次建立連線時的密碼驗證竟然成了瓶頸所在。希望大家慎用。可以選擇封閉MongoDB所在主機的外網IP,然後使用內網無密碼訪問最佳。 
之後進行伺服器效能優化,在頻繁呼叫的幾個介面緊急使用快取來緩解問題。而一些不重要不需要及時更新的查詢則切換到從庫進行查詢。並切掉了一些需要及時更新的資料介面也訪問從庫,需要mark下資料庫緩解後再調整回去。 
經過追查每一個表的索引發現,資料表中有很多冗餘索引,有一些沒有作為索引條件查詢,有一些已經被建為聯合索引,卻依然沒有刪除掉。果斷Drop掉這些Index。 
這之後資料的讀寫佇列在300-1000左右,依然是不健康的狀態。 

五、再一次定位問題

這之後MongoDB一直在不健康的狀態但是並沒有再一次宕機。不過危險依然存在。 
MongoDB的佔用的記憶體熱點資料依然是5GB左右。崩潰了。 
定位問題到MongoDB的資料由於不在記憶體中,所以導致讀寫速度障礙。 
寫了一段Java程式進行R710資料庫資料迴圈插入,希望能測試出是否可以提高記憶體佔用量。 
果然,結果是插入一段時間之後。MongoDB的記憶體佔用已經到達36GB。理想中的結果。 
不過線上環境不能隨便插入資料,所以使用python寫了一段全表掃描資料的指令碼執行。 
結果竟然無效。 
推論是插入會直接放入熱點中,查詢可能是需要經歷一段時間和幾次的命中才會。坑爹。 
目前能做的就是等待,等待MongoDB的熱點記憶體佔用提高,才能緩解所有問題。直到Mongos測試OK

六、其實。。最重要的地方在這裡

問題主因就是優化不足,還輕率的進行了資料庫切換。 
MongoDB在R410時候執行,所有的熱點資料在記憶體對映Mapping。而R710沒有,需要再規則下重新進行對映。 
最坑爹的就是這裡。這段時間需要很久。而資料庫重啟導致使用者重連服務,暴起的連線數和請求數直接壓垮資料庫。 
甚至會導致資料庫啟動就宕機的危險。 

七、動作要謹慎。Over