MongoDB集羣負載不均衡問題定位及解決

一、問題描述app

這是一套運行在騰訊雲上的MongoDB 3.6版本集羣,共5個分片,每片規格是6核16GB。post

在壓測的過程當中,發現第3個分片的CPU使用率長時間高達96%,其它4個分片的CPU使用率都沒有超過10%。ui

 

二、思考及分析spa

首先,我查看慢日誌,發現大量與postbox相關的query,半個小時內出現9000屢次,每次請求平均耗時200ms左右,planSummary爲IXSCAN,每次掃描和返回的文檔數都不多,鎖也不多。日誌

1  planSummary: IXSCAN { serviceUserId: 1, updatedDate: -1, messageType: 1 } keysExamined:0 docsExamined:0 cursorExhausted:1 numYields:0 nreturned:0 reslen:340 locks:{ Global: { acquireCount: { r: 2 } }, Database: { acquireCount: { r: 1 } }, Collection: { acquireCount: { r: 1 } } }

到此,還不能說明問題,可是既然慢日誌裏面都是與postbox有關的,那麼我就去檢查一下這個collectioncode

如下是db.getCollection('postbox').stats()的輸出:blog

{ 
    "sharded" : true, 
    "capped" : false, 
    "ns" : "postbox.postbox", 
    "count" : 1020.0, 
    "size" : 301694.0, 
    "storageSize" : 163840.0, 
    "totalIndexSize" : 184320.0, 
    "indexSizes" : {
        "_id_" : 69632.0, 
        "expireAtTtlIndex" : 53248.0, 
        "serviceUserIdMsgTypeSearchIdx" : 61440.0
    }, 
    "avgObjSize" : 295.0, 
    "nindexes" : 3.0, 
    "nchunks" : 1.0, 
    "shards" : {
        "cmgo-280eoxk3_2" : {
   ……
   省略

}

能夠看出,整個文檔只有294KB,包含一個chunk,只分布在"cmgo-280eoxk3_2"這一個節點。這就能夠說明爲何這一個節點的負載高,而其它節點負載很低了。ci

經過執行sh.status(),能夠看到該collection的分片方式爲range:文檔

                postbox.postbox
                        shard key: { "serviceUserId" : 1 }
                        unique: false
                        balancing: true
                        chunks:
                                cmgo-280eoxk3_2    1
                        { "serviceUserId" : { "$minKey" : 1 } } -->> { "serviceUserId" : { "$maxKey" : 1 } } on : cmgo-280eoxk3_2 Timestamp(1, 0) 

因此,這個問題的根本緣由是:該collection目前數據很是少,只有一個chunk,只分布在一個節點中,因此壓測就致使該節點的負載很是高。get

 

三、解決方法

查閱官方文檔,其中有以下說明:

If you shard an empty collection using a hashed shard key, MongoDB automatically creates two empty chunks per shard, to cover the entire range of the hashed shard key value across the cluster. 
You can control how many chunks MongoDB creates with the numInitialChunks parameter to shardCollection or by manually creating chunks on the empty collection using the split command.

意思是使用hashed分片方式,MongoDB會自動爲每一個片建立2個空的chunks,你也能夠在設置該集合的分片時,使用numInitialChunks參數來指定空chunks的數量。

經過與研發溝通,結合咱們的實際狀況評估,認爲該collection可使用hashed分片方式。

因此,備份該集合的數據,而後使用以下方從新指定分片方式,最後導入數據。

db.runCommand( { shardCollection: "postbox.userPostIndex", key: {serviceUserId:"hashed"}, numInitialChunks: 3 } )

相關文章
相關標籤/搜索