1. 程式人生 > >記一次MongoDB效能問題(從MySQL遷移到MongoDB)

記一次MongoDB效能問題(從MySQL遷移到MongoDB)

最近忙著把一個專案從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是什麼東西,所以沒有處理,只是把問題反饋給了運維人員,後來知道運維人員也沒有理會這茬兒,所以問題的序幕就這樣拉開了。

遷移工作需要匯入舊資料。MongoDB本身有一個mongoimport工具可供使用,不過它只接受json、csv等格式的原始檔,不適合我的需求,所以我沒用,而是用PHP寫了一個指令碼,平穩運行了一段時間後,我發現數據匯入的速度下降了,同時PHP丟擲異常:

cursor timed out (timeout: 30000, time left: 0:0, status: 0)

我一時判斷不出問題所在,想想先在PHP腳本里加大Timeout的值應付一下:

1 2 3 <?php MongoCursor::$timeout = -1; ?>

可惜這樣並沒有解決問題,錯誤反倒變著花樣的出現了:

max number of retries exhausted, couldn't send query, couldn't send query: Broken pipe

接著使用strace跟蹤了一下PHP指令碼,發現程序卡在了recvfrom操作上:

1 2 shell> strace -f -r -p <PID> recvfrom(<FD>,

通過如下命令查詢recvfrom操作的含義:

1 2 shell> apropos recvfrom receive a message from a socket

或者按照下面的方式確認一下:

1 2 shell> lsof -p <PID> shell> ls -l /proc/<PID>/fd/<FD>

此時如果查詢MongoDB的當前操作,會發現幾乎每個操作會消耗大量的時間:

1 mongo> db.currentOp()

與此同時,執行mongostat的話,結果會顯示很高的locked值。

我在網路上找到一篇:MongoDB Pre-Splitting for Faster Data Loading and Importing,看上去和我的問題很類似,不過他的問題實質是由於自動分片導致資料遷移所致,解決方法是使用手動分片,而我並沒有使用自動分片,自然不是這個原因。

詢問了幾個朋友,有人反映曾遇到過類似的問題,在他的場景裡,問題的主要原因是系統IO操作繁忙時,資料檔案預分配堵塞了其它操作,從而導致雪崩效應。

為了驗證這種可能,我搜索了一下MongoDB日誌:

1 2 3 shell> grep FileAllocator /path/to/log [FileAllocator] allocating new datafile ... filling with zeroes... [FileAllocator] done allocating datafile ... took ... secs

我使用的檔案系統是ext4(xfs也不錯 ),建立資料檔案非常快,所以不是這個原因,但如果有人使用ext3,可能會遇到這類問題,所以還是大概介紹一下如何解決:

MongoDB按需自動生成資料檔案:先是<DB>.0,大小是64M,然後是<DB>.1,大小翻番到128M,到了<DB>.5,大小翻番到2G,其後的資料檔案就保持在2G大小。為了避免可能出現的問題,可以採用事先手動建立資料檔案的策略:

1 2 3 4 5 6 7 8 9 10 11 12 13 #!/bin/sh DB_NAME=$1 cd /path/to/$DB_NAME for INDEX_NUMBER in {5..50}; do FILE_NAME=$DB_NAME.$INDEX_NUMBER if [ ! -e $FILE_NAME ]; then head -c 2146435072 /dev/zero > $FILE_NAME fi done

注:數值2146435072並不是標準的2G,這是INT整數範圍決定的。

最後一個求助方式就是官方論壇了,那裡的國際友人建議我檢查一下是不是索引不佳所致,死馬當活馬醫,我激活了Profiler記錄慢操作:

1 2 mongo> use <DB> mongo> db.setProfilingLevel(1);

不過結果顯示基本都是insert操作(因為我是匯入資料為主),本身就不需要索引:

1 2 mongo> use <DB> mongo> db.system.profile.find().sort({$natural:-1})

問題始終沒有得到解決,求人不如求己,我又重複了幾次遷移舊資料的過程,結果自然還是老樣子,但我發現每當出問題的時候,總有一個名叫irqbalance的程序CPU佔用率居高不下,搜尋了一下,發現很多介紹irqbalance的文章中都提及了NUMA,讓我一下子想起之前在日誌中看到的警告資訊,我勒個去,竟然繞了這麼大一個圈圈!安下心來仔細翻閱文件,發現官方其實已經有了相關介紹,按如下設定搞定:

1

相關推薦

openstack 雲主機熱遷移失敗與恢復過程

openstack 遷移失敗 背景:最近把openstack上的所有機器的磁盤逐一重新分區,之前是兩塊磁盤用RAID1,但是ceph已經配置了3份副本,這樣相當於存6份副本了,目前磁盤資源不太夠。機器用的是HP P440ar的陣列卡,支持建立不同模式的邏輯卷,所以把磁盤分區修改為RAID1系統盤+RA

asm磁碟組資料遷移案例

前     言資料庫在新增資料檔案時報錯:ORA-01119,ORA-17520,ORA-00600錯誤,根據報錯無法判斷故障點,而且生產庫無法進行其他測試,比較穩妥的辦法是新建一個磁碟組,將現有的資料遷移到新的磁碟組上。環境介紹作業系統:solaris 11資料庫版本:11

wordpress效能優化

wordpress真的很流行,但是我真的不認為它的效能好,尤其當資料超過幾萬十幾萬的時候。當然作為一個個人部落格來說超過幾萬的資料是一件很難的事情。可我現在用wordpress作為CMS使用,資料庫中有十幾萬條資料。 新租的雲主機配置為:2核2GHZ的CPU、1G記憶體、

蘋果APP賬號續費到釋出成功的歷程

一、一波三折的續費      最近公司開發的蘋果APP的SSL證書到期了,計劃重新發布一下該APP,已替換即將到期的SSL證書。近幾年隨著釘釘、企業微信等線上辦公軟體超級平臺的出現,各企業都會選擇其中一個平臺作為本企業的移動辦公平臺,其他系統都與該平臺整合,所以最近幾年使用單獨的APP開發

介面效能優化實踐總結:優化介面效能的八個建議

### 前言 最近對外介面偶現504超時問題,原因是程式碼執行時間過長,超過nginx配置的15秒,然後真槍實彈搞了一次介面效能優化。在這裡結合優化過程,總結了介面優化的八個要點,希望對大家有幫助呀~ - 資料量比較大,批量操作資料入庫 - 耗時操作考慮非同步處理 - 恰當使用快取 - 優化程式邏輯、程式碼

MongoDB效能問題(MySQL遷移MongoDB)

最近忙著把一個專案從MySQL遷移到MongoDB,在匯入舊資料的過程中,遇到了些許波折,犯了不少錯誤,但同時也學到了不少知識,遂記錄下來,需要的朋友可以參考下 公司為這個專案專門配備了幾臺高效能務器,清一色的雙路四核超執行緒CPU,外加32G記憶體,運維人員安裝好Mo

MySQL遷移MySQL5.6升級到5.7後查詢慢了幾十倍的問題

打印 ins 狀態 sql語句 top 引用 為什麽 區別 image 起因 因為生產環境數據量越來越大,客戶越來越多,項目功能也越來越多,項目本身也越來越多,導致之前的服務器內存、硬盤都已經漸漸的不夠用了,當時出現了2種解決方案,增加服務器配置和新購服務器,但是就算是新增

MSSQL到MySQL大資料遷移過程

工作中遇到一個需求 要將MSSQL資料庫中共計12張表的資料大概1000W行資料遷移到MySQL資料庫中,去年另一個同事負責這件事情,他採用的方法是先將MSSQL資料庫裡的資料生成同MySQL資料庫表結構一致的12張表,然後用我提供的一個delphi寫的一個工具來進行遷移。工具用的UniDAC的TCRBa

Oracle資料庫遷移Mysql資料庫的過程

 很簡單,我用的Navicat for mysql 12 搞定的 首先用 Navicat for mysql 連結上這兩個資料庫 然後    工具--資料傳輸 然後選擇好 源資料庫 和目標資料庫 然後在 選項 tab 勾上 遇到錯誤時繼續 然後一路下

MongoDB效能問題+Linux記憶體管理學習筆記--實體記憶體分配

最近忙著把一個專案從MySQL遷移到MongoDB,在匯入舊資料的過程中,遇到了些許波折,犯了不少錯誤,但同時也學到了不少知識,遂記錄下來。 公司為這個專案專門配備了幾臺高效能務器,清一色的雙路四核超執行緒CPU,外加32G記憶體,運維人員安裝好MongoDB後,就交我手裡了,我習慣於在使用新伺服器前先看

Mongodb---事故故障

free 連接 最小 idt 日誌 垃圾清理 清空 mongodb -m 2014.06.19.001---故障報告 事故發生時間 事故簡述 事故責任方 是否解決 19:21-20:15 IISserverD盤即將溢出

mysql事故---紀念逝去的一上午

not 路徑 內部 oca oss ica relay its scala 虛擬機關機後第二天mysql起不來,回想一下我關機前和關機後的操作發現:關機前沒關閉mysqld服務就直接init 0了,關機後將虛擬機內存由1G降到724M。筆者保證再也做過別的騷操作了。

mysql中文字符亂碼的問題排查

mysql mysql中文亂碼 mysql字符集 今天開發反應兩樣的程序往一個庫裏面插入數據正常,往另外一個庫裏面插入數據有亂碼。第一反應就是兩個數據庫關於字符集的配置不一樣。在兩個庫分別查看參數:show variables like "%char%";+--------------------

RAID陣列的遷移經歷

行遷移 abs 一次 操作 常開 tabs 重啟 控制器 型號 xu言: 最近,某電信機房因為空調漏水問題導致了我司的Dell R430 服務器的主板及CPU不同程度受損。服務器已經不能正常開機。但是,又基於把服務器的數據需要最短時間進行恢復。抱著試試看的心裏進行了磁盤整體

MySQL存儲過程和遊標的使用

MySQL存儲過程 MySQL遊標 需求: 有三張表:Player、Consumption、Consumption_other。Player表中記錄用戶信息(playerid、origin等字段),Consumption和Consumption_other記錄用戶的消費信息。現需要根據Playe

mysql數據庫刪除恢復的案例

mysql 數據恢復 linux emmmmm 今天晚上十一點有個朋友說他的數據庫刪除了。是昨天刪除的。我就日了mmp 了數據庫不做備份的??????????what fuck 那就登陸服務器看看吧看到還有一個4 月22 號的。那麽就新建一個數據庫導入進去唄導入導入之後改下源代碼看看能不能訪問e

springboot訪問linux的mysql數據庫

enable rac boot data jar expire 訪問權限 默認 登錄 今天使用springboot連接linux的mysql,期間一直報錯,這裏簡單記錄一下過程。 工具:idea-2017,linux-7.x,mysql-5.6.40。 首先說一下這幾個註解

線上MySQL數據庫死鎖問題

重復 成功 中一 主鍵 adl 一次 his TE BE 最近線上項目報了一個MySQL死鎖(DealLock)錯誤,雖說對業務上是沒有什麽影響的,由於自己對數據庫鎖這塊了解不是很多,之前也沒怎麽的在線上碰到過。這次剛好遇到了,便在此記錄一下。 出現

常規的Mysql數據庫訪問的時間分析

客戶端 tcp三次握手 alt 時間 res src img gree 分析 背景:記一次常規的數據訪問的時間分析(插入操作) 1. TCP三次握手 SYN ---> <--- SYN,ACK ACK ---> 花費時間: 386.718-38

【國慶】mysqld_safe引發mysql進程故障

更新mysql 小結 未能 should sta 服務 tro boot 競爭力 今天是舉國歡慶的日誌,身為奮青的我,學習和工作,首日計劃安排必須是學習任務呀;但是今天心血來潮,Mariadb密碼忘記了,於是巴拉巴拉的執行"mysqld_safe --skip-grant-