本文介紹如何查看增加Shard節點或刪除Shard節點的任務進度,以及檢查是否有異常阻塞任務進程的方法。
背景資訊
當您對分區叢集執行個體執行增加Shard節點或刪除Shard節點操作後,可能會出現任務提交後很長時間都沒完成的情況,以下內容將指導您如何檢查上述問題。
在進行操作前,您需要瞭解以下基本知識:
瞭解MongoDB複本集執行個體和分區叢集執行個體的部署模式以及兩種架構之間的區別。更多介紹,請參見複本集架構和分區叢集架構。
瞭解均衡器Balancer的基本工作原理。更多介紹,請參見管理MongoDB均衡器Balancer。
瞭解MongoDB資料的劃分方式,MongoDB的資料是根據Chunk(塊)進行劃分的。
瞭解MongoDB分區叢集執行個體常見的營運命令,例如
sh.status()
等。瞭解mongo shell、mongosh或其他視覺化檢視的基礎使用方式。
檢查任務進程
步驟一:檢查Balancer是否開啟
在增加或刪除分區任務中,Chunk的遷移是依賴Balancer完成的。如果未開啟Balancer則會導致如下情況:
新增Shard節點:Chunk資料無法遷移到新的Shard節點上,同時也無法承載業務流量。
刪除Shard節點:待刪除Shard節點上的Chunk資料無法遷移,導致刪除Shard節點的任務被阻塞。
因此,您需要開啟Balancer來保障Chunk資料的正常遷移。開啟Balancer的方法,請參見管理MongoDB均衡器Balancer。
確認Balancer是否開啟有如下兩種方法:
方法一:
sh.status()
命令Balancer已開啟的狀態下,返回樣本如下。
... autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: yes Balancer active window is set between 08:30 and 11:30 server local time ...
如果顯示
“Currently enabled: no”
,則表示Balancer未開啟。方法二:
sh.getBalancerState()
命令如果返回
true
,則表示已開啟Balancer。如果返回
false
,則表示未開啟Balancer。
步驟二:檢查Balancer視窗期是否過小
Balancer控制了Chunk資料移轉的速度,Balancer僅會在視窗期時間段內遷移Chunk資料,若當前視窗期未遷移完成,會在下個視窗期繼續遷移,直至遷移完成。當視窗期過小時,可能會拖慢增加Shard節點或刪除Shard節點任務流的整體進度。調整Balancer視窗期的方法,請參見管理MongoDB均衡器Balancer。
您可以通過如下兩種方法檢查Balancer的視窗期:
方法一:
sh.status()
命令返回樣本如下,可以瞭解到Balancer的視窗期為當地時間的08:30至11:30,共計3個小時。
... autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: yes Balancer active window is set between 08:30 and 11:30 server local time ...
方法二:
sh.getBalancerWindow()
命令返回樣本如下,當執行個體中的分區集合較多時,採用此方法能夠更直觀的顯示視窗期時間。
{ "start" : "08:30", "stop" : "11:30" }
步驟三:擷取預估任務進度的必要資訊
評估任務進度前,您需要擷取Balancer的運行結果(成功和失敗數量的統計)以及待遷移分區表的Chunk資訊。
您可以通過如下兩種方法擷取Balancer的運行結果和待遷移分區表Chunk資訊:
方法一:通過
sh.status()
命令的輸出結果擷取sh.status()
命令的輸出結果僅需要關注兩部分資訊,第一部分為最近時間Balancer啟動並執行結果,樣本如下。... balancer: Collections with active migrations: <db>.<collection> started at Wed Sep 27 2023 10:25:21 GMT+0800 (CST) Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: 300 : Success databases: ...
第二部分為待遷移的分區表的Chunk資訊,樣本如下。
... databases: ... { "_id" : "<db>", "primary" : "d-xxxxxxxxxxxxxxx3", "partitioned" : true, "version" : { "uuid" : UUID("3409a337-c370-4425-ad72-8b8c6b0abd52"), "lastMod" : 1 } } <db>.<collection> shard key: { "<shard_key>" : "hashed" } unique: false balancing: true chunks: d-xxxxxxxxxxxxxxx1 13630 d-xxxxxxxxxxxxxxx2 13629 d-xxxxxxxxxxxxxxx3 13652 d-xxxxxxxxxxxxxxx4 13630 d-xxxxxxxxxxxxxxx5 3719 too many chunks to print, use verbose if you want to force print ...
以上樣本中的“d-xxxxxxxxxxxxxxx5”即為新增的Shard節點。您也可以在分區表所在的庫執行
getShardDistribution
命令來擷取Chunk資料的分布資訊,樣本如下。use <db> db.<collection>.getShardDistribution()
方法二:直接讀取config庫中的相關資訊
查看Chunks統計,按分區彙總,樣本如下。
db.getSiblingDB("config").chunks.aggregate([{$group: {_id: "$shard", count: {$sum: 1}}}])
查看指定分區上的Chunks,按namespace彙總,樣本如下。
db.getSiblingDB("config").chunks.aggregate([{$match: {shard: "d-xxxxxxxxxxxxxx"}},{$group: {_id: "$ns", count: {$sum: 1}}}])
查看過去1天內成功遷移到指定Shard節點的Chunk數量,樣本如下。
// details.to指定chunk遷移的目標shard // time欄位用ISODate指定時間範圍 db.getSiblingDB("config").changelog.find({"what" : "moveChunk.commit", "details.to" : "d-xxxxxxxxxxxxx","time" : {"$gte": ISODate("2023-09-26T00:00:00")}}).count()
步驟四:預估任務進度及完成時間
擷取分區表已成功遷移的Chunk數量以及當前分區表資料分布情況後,您就可以預估出任務的整體進度和預期完成時間。
假如當前增加Shard節點的情境中,總Chunk數量保持不變,Shard節點數量也保持不變(期間不會有新增或刪除Shard節點的任務),增加Shard節點的過程中業務負載基本保持固定,且Balancer的參數設定均為預設值。以上述步驟的樣本為例,可以得知以下資訊:
Shard節點數量為5。
在Balancer視窗期內,成功遷移的Chunk數量為300個。
分區表
<db>.<collection>
的總Chunk數量為58260個(13630+13629+13652+13630+3719=58260)。
因此可以計算出:
達到均衡狀態時,每個分區上的Chunk數量應為11652個(58260÷5=11652)。
按照當前的遷移速度,任務完成還需要26.4天((11652-3719)÷300≈26.4)。
該增加Shard節點任務進度為32%(3719÷11652=32%)。
實際的業務情境中,總Chunk數量還會隨著業務寫入以及Chunk分裂而增加。因此假設條件為理想情況,實際耗時可能會更久。
步驟五:確認任務流是否阻塞(刪除Shard節點)
如果刪除Shard節點的任務被阻塞,執行sh.status()
命令後,返回資訊中沒有看到過去時間段有Chunk資料移轉成功,且待刪除Shard節點上依然殘留部分Chunk資料未遷移走。此時刪除Shard節點任務無法完成,並且會影響您在ApsaraDB for MongoDB控制台對執行個體的其他營運操作。
上述情境中sh.status()
命令的返回資訊樣本如下圖所示。
出現上述問題可能是因為Jumbo Chunk阻塞了刪除Shard節點的進程,您可以通過如下的命令確認。
db.getSiblingDB("config").chunks.aggregate([{$match: {shard: "d-xxxxxxxxxxxxxx", jumbo:true}},{$group: {_id: "$ns", count: {$sum: 1}}}])
一般情況下,出現Jumbo Chunk是因為設計的分區鍵(Shard Key)不合理(例如存在熱點Key)等因素導致。您可以在業務側進行如下方法嘗試解決:
如果您的MongoDB資料庫的大版本為4.4,則可以通過refineCollectionShardKey命令來最佳化您的Shard key設計,通過為原本分區鍵添加尾碼的方式來使得分區鍵的基數更大,從而解決Jumbo Chunk的問題。
如果您的MongoDB資料庫的大版本為5.0及以上,則可以通過reshardCollection命令來將指定分區表按照新的分區鍵重新分區。更多介紹,請參見Reshard a Collection。
如果您確認部分業務資料可刪除的話,則可以刪除對應Jumbo Chunk中的資料,該方法可以減少Jumbo Chunk的大小。減少資料後Jumbo Chunk可能成為一個普通的Chunk,然後被均衡器Balancer遷出。
您可以調大
chunkSize
參數來使判斷Jumbo Chunk的條件發生變化,建議在阿里雲支援人員工程師的協助下進行操作。
如果以上方法都無法解決您的問題,建議您提交工單聯絡支援人員協助解決。
加速新增或刪除任務進程
如果您希望增加Shard節點或刪除Shard節點的整體流程可以在更短的時間內完成,您可以嘗試以下加速方法:
將Balancer的視窗期時間調大,Chunk遷移過程帶來的額外負載可能會對業務側產生影響,請您評估風險後再進行調整。調整Balancer視窗期的方法,請參見管理MongoDB均衡器Balancer。
在業務低峰期手動執行
moveChunk
操作,更多介紹,請參見sh.moveChunk()。樣本如下。sh.moveChunk("<db>.<collection>", {"<shard_key>": <value>}, "d-xxxxxxxxxxxxx") // example: sh.moveChunk("records.people", { zipcode: "53187" }, "shard0019")
提交工單聯絡支援人員對相關核心參數進行調整。