標籤:
最近忙著把一個項目從MySQL遷移到MongoDB,在匯入舊資料的過程中,遇到了些許波折,犯了不少錯誤,但同時也學到了不少知識,遂記錄下來。
公司為這個項目專門配備了幾台高效能務器,清一色的雙路四核超執行緒CPU,外加32G記憶體,營運人員安裝好MongoDB後,就輪到我了,我習慣於在使用新伺服器前先看看相關日誌,瞭解一下基本情況,當我瀏覽MongoDB日誌時,發現一些警告資訊:
WARNING: You are running on a NUMA machine.We suggest launching mongod like this to avoid performance problems:numactl --interleave=all mongod [other options]
當時我並不太清楚NUMA是什麼東西,所以沒有處理,只是把問題報告給了營運人員,事實證明營運人員也沒有處理,所以問題的序幕就這樣拉開了…
遷移工作首先要匯入舊資料。開始一切倒還正常,不過幾小時之後,我無意中發現不知道什麼時候開始資料匯入的速度下降了,同時我的PHP指令碼開始不停的拋出異常:
cursor timed out (timeout: 30000, time left: 0:0, status: 0)
我一時判斷不出問題所在,想想先在PHP指令碼裡加大Timeout的值應付一下:
MongoCursor::$timeout = -1;
可惜這樣並沒有解決問題,錯誤反倒變著花樣的出現了:
max number of retries exhausted, couldn‘t send querycouldn‘t send query: Broken pipe
無奈之下用strace跟蹤了一下PHP指令碼:
shell> strace -p <PID>
發現進程卡在了recvfrom操作上:
recvfrom(<FD>,
通過如下命令查詢recvfrom操作的含義是:receive a message from a socket
shell> apropos recvfrom
還可以按照下面的方式確認一下:
shell> lsof -p <PID>shell> ls -l /proc/<PID>/fd/<FD>
此時查詢MongoDB當前操作,發現幾乎每個操作會消耗大量的時間:
shell> echo "db.currentOp()" | /path/to/mongo
同時運行mongostat顯示很高的locked值。
…
重複做了很多工作,但始終無法找到問題的癥結在哪裡,只好求助官方論壇,那裡的支援人員都很熱心,在我描述了問題後,沒過多久就有了回複,建議我檢查一下是不是索引不佳所致,為了驗證這種可能,我啟用了Profiler記錄慢操作:
mongo> use <DB>mongo> db.setProfilingLevel(1);
不過結果顯示基本都是insert操作(因為我是匯入資料為主),本身就不需要索引:
mongo> use <DB>mongo> db.system.profile.find().sort({$natural:-1})
…
問題到了這裡,似乎已經走投無路了,為了死馬當活馬醫,我又重複了幾次遷移舊資料的過程,結果自然是次次都出問題,但幸運的是我發現每當出問題的時候,在top命令的結果中,總有一個名叫irqbalance的進程居高不下,搜尋了一下,結果很多介紹irqbalance的文章中都提及了NUMA,讓我一下子記起之前在日誌中看到的警告資訊,於是乎按照資訊裡介紹的,重新啟動了一下MongoDB:
shell> numactl --interleave=all /path/to/mongod
一切都正常了。為瞭解決這個問題,浪費了很多精神,實在沒有力氣再解釋NUMA到底是什麼東西了,有想瞭解的網友可以參考老外的文章,裡面的介紹很翔實。
原文連結:huoding.com
對於罪魁禍首,作者留給大家去學習,NoSQLFan在這裡可以給大家做一個簡單的描述,先解釋幾個概念
NUMA:NUMA是多核心CPU架構中的一種,其全稱為Non-Uniform Memory Access,簡單來說就是在多核心CPU中,機器的實體記憶體是分配給各個核的,架構簡圖如下所示:
每個核訪問分配給自己的記憶體會比訪問分配給其它核的記憶體要快,有下面幾種存取控制策略:
- 1.預設(default):總是在本地節點分配(分配在當前進程啟動並執行節點上);
- 2.綁定(bind):強制分配到指定節點上;
- 3.交叉(interleave):在所有節點或者指定的節點上交織分配;
- 4.優先(preferred):在指定節點上分配,失敗則在其他節點上分配。
上面文章中最後使用numactl –interleave命令就是指定其為交叉共用模式。
irqbalance:這是作者在上面提到的一個佔用CPU的進程,這個進程的作用是在多核心CPU的作業系統中,分配系統中斷訊號的。參見:irqbalance.org
概念說完了,下面是上面問題的簡單描述:
我們知道虛擬記憶體機制是通過一個中斷訊號來通知虛擬記憶體系統進行記憶體swap的,所以這個irqbalance進程忙,是一個危險訊號,在這裡是由於在進行頻繁的記憶體交換。這種頻繁交換現象稱為swap insanity,在MySQL中經常提到,也就是在NUMA架構中,採用不合適的策略,導致核心只能從指定記憶體塊節點上分配記憶體,即使總記憶體還有富餘,也會由於當前節點記憶體不足時產生大量的swap操作。
對於NUMA,進一步瞭解可以參考:NUMA與英特爾下一代Xeon處理器 和MySQL單機多執行個體方案 兩篇文章
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
mongodb效能問題及原理分析