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


1、問題描述

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

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

 

2、思考及分析

首先,我查看慢日志,發現大量與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有關的,那么我就去檢查一下這個collection

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

{ 
    "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"這一個節點。這就可以說明為什么這一個節點的負載高,而其它節點負載很低了。

通過執行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,只分布在一個節點中,所以壓測就導致該節點的負載非常高。

 

3、解決方法

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

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 } )


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM