このトピックでは、シャードノードを追加または削除するタスクの進捗を監視する方法と、これらのタスクをブロックする可能性のある異常な状態を特定する方法について説明します。
背景情報
シャードクラスターインスタンスにシャードノードを追加または削除した後、タスクが長期間完了しない場合があります。以下のセクションでは、この問題のトラブルシューティング方法について説明します。
開始する前に、以下の概念を理解してください。
-
MongoDB のレプリカセットインスタンスとシャードクラスターインスタンスのデプロイモード、およびこれらのアーキテクチャの違いを理解します。詳細については、「レプリカセットアーキテクチャ」および「シャードクラスターアーキテクチャ」をご参照ください。
-
MongoDB バランサーの仕組みを理解します。詳細については、「MongoDB バランサーの管理」をご参照ください。
-
MongoDB がデータをどのように分割するかを理解します。MongoDB はデータをチャンクに分割します。
-
MongoDB シャードクラスターインスタンスの一般的な O&M コマンド (例:
sh.status()) を理解します。 -
mongo シェル、`mongosh`、またはその他の可視化ツールの使用方法を理解します。
タスク進捗の確認
ステップ 1:バランサーが有効になっているかの確認
シャードの追加または削除中のチャンク移行は、バランサーに依存します。バランサーが無効になっている場合、以下の問題が発生します。
-
シャードノードの追加時:チャンクデータが新しいシャードノードに移行できず、ノードがサービストラフィックを処理できません。
-
シャードノードの削除時:ターゲットシャード上のチャンクが移行できず、削除タスクがブロックされます。
バランサーを有効にして、正常なチャンク移行を確保してください。手順については、「MongoDB バランサーの管理」をご参照ください。
以下のいずれかの方法を使用して、バランサーが有効になっているかを確認します。
-
方法 1:
sh.status()コマンドを実行します。バランサーが有効な場合、出力は次の例のようになります。
... 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”と表示される場合、バランサーは無効になっています。 -
方法 2:
sh.getBalancerState()コマンドを実行します。-
コマンドが
trueを返す場合、バランサーは有効です。 -
コマンドが
falseを返す場合、バランサーは無効です。
-
ステップ 2:バランサーウィンドウが短すぎないかの確認
バランサーはチャンクの移行速度を制御し、アクティブウィンドウ中にのみチャンクを移行します。現在のウィンドウ内で移行が完了しない場合、完了するまで次のウィンドウで再開されます。ウィンドウが短いと、シャードの追加または削除タスクが遅くなる可能性があります。バランサーウィンドウを調整するには、「MongoDB バランサーの管理」をご参照ください。
以下のいずれかの方法を使用して、バランサーウィンドウを確認します。
-
方法 1:
sh.status()コマンドを実行します。次の例は、ローカルサーバー時間の 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 ... -
方法 2:
sh.getBalancerWindow()コマンドを実行します。次の例は、ウィンドウ時間を明確に表示しており、多くのシャード化されたコレクションが存在する場合に特に役立ちます。
{ "start" : "08:30", "stop" : "11:30" }
ステップ 3:タスク進捗の推定に必要な情報の収集
MongoDB 6.0 より前のバージョン
このセクションは、以下のバージョンに適用されます。
-
MongoDB 6.0 より前のバージョンのインスタンス。
-
マイナーエンジンバージョンが 7.0.1 (ベースラインバージョン 6.0.3) より前の MongoDB 6.0 インスタンス。マイナーエンジンバージョンを確認するには、「MongoDB マイナーバージョンガイド」をご参照ください。
タスクの進捗を推定する前に、バランサーの実行統計 (成功数と失敗数) と、移行を待機しているシャード化されたコレクションのチャンク情報を取得します。
以下の 2 つの方法を使用して、バランサーの実行結果と、移行待ちのシャード化されたテーブルのチャンクに関する情報を取得できます。
-
方法 1:
sh.status()コマンドの出力を使用します。sh.status()の出力の 2 つの部分に注目します。最初の部分は、この例のように、最近のバランサーの結果を示しています。... 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: ...2 番目の部分は、この例のように、シャード化されたコレクションのチャンク詳細を示しています。
... 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」が新しく追加されたシャードノードです。また、シャード化されたコレクションを含むデータベースで
getShardDistributionコマンドを実行して、以下に示すようにチャンクの分散詳細を取得することもできます。use <db> db.<collection>.getShardDistribution() -
方法 2:config データベースから関連データを直接読み取ります。
シャードごとに集計されたチャンク統計を次のように表示します。
db.getSiblingDB("config").chunks.aggregate([{$group: {_id: "$shard", count: {$sum: 1}}}])特定のシャード上のチャンクを名前空間でグループ化して表示するには、次のコマンドを実行します。
db.getSiblingDB("config").chunks.aggregate([{$match: {shard: "d-xxxxxxxxxxxxxx"}},{$group: {_id: "$ns", count: {$sum: 1}}}])過去 24 時間に特定のシャードノードに正常に移行されたチャンクをカウントするには、次のコマンドを実行します。
// details.to はチャンク移行の移行先シャードを指定します // ISODate を使用して time フィールドの時間範囲を定義します db.getSiblingDB("config").changelog.find({"what" : "moveChunk.commit", "details.to" : "d-xxxxxxxxxxxxx","time" : {"$gte": ISODate("2023-09-26T00:00:00")}}).count()
MongoDB 6.0 以降のバージョン
このセクションは、以下のバージョンに適用されます。
-
MongoDB 6.0 以降のバージョンのインスタンス。
-
マイナーエンジンバージョンが 7.0.1 (ベースラインバージョン 6.0.3) 以降の MongoDB 6.0 インスタンス。マイナーエンジンバージョンを確認するには、「MongoDB マイナーバージョンガイド」をご参照ください。
タスクの進捗を推定する前に、シャード間のデータ分散に注目します。引き続き sh.status() の出力を参照として使用できますが、不均一なチャンク数から実際のデータ量分散に注意を移してください。
-
シャード化されたコレクションの分散とデータバランスに関する情報を取得します。
getShardDistributionコマンドを使用して分散の詳細を取得し、データバランスに注目します。例:mongos> db.xxx.getShardDistribution() Shard d-xxx at xxx data : 379.26MiB docs : 8277367 chunks : 1 estimated data per chunk : 379.26MiB estimated docs per chunk : 8277367 Shard d-xxx at xxx data : 379.11MiB docs : 8272852 chunks : 1 estimated data per chunk : 379.11MiB estimated docs per chunk : 8272852 Shard d-xxx at xxx data : 379.18MiB docs : 8275108 chunks : 1 estimated data per chunk : 379.18MiB estimated docs per chunk : 8275108 Totals data : 1.11GiB docs : 24825327 chunks : 3 Shard d-xxx contains 33.34% data, 33.34% docs in cluster, avg obj size on shard : 48B Shard d-xxx contains 33.32% data, 33.32% docs in cluster, avg obj size on shard : 48B Shard d-xxx contains 33.33% data, 33.33% docs in cluster, avg obj size on shard : 48Bまた、次のコマンドを実行して、より詳細な分散情報 (ドキュメント数、合計サイズ、孤立ドキュメント数、孤立サイズを含む) を取得することもできます。
db.getSiblingDB("admin").aggregate( [{ $shardedDataDistribution: { } },{ $match: { "ns": "<db>.<collection>" } }] ).pretty()次の出力例は、シャード間で顕著なデータ不均衡があることを示しています。
{ "ns" : "<db>.<collection>", "shards" : [ { "shardName" : "d-xxxxxxxxxxxxxxx1", "numOrphanedDocs" : 0, "numOwnedDocuments" : 504298920, "ownedSizeBytes" : NumberLong("833101815840"), "orphanedSizeBytes" : 0 }, { "shardName" : "d-xxxxxxxxxxxxxxx2", "numOrphanedDocs" : 0, "numOwnedDocuments" : 250283901, "ownedSizeBytes" : NumberLong("409714745937"), "orphanedSizeBytes" : 0 }, { "shardName" : "d-xxxxxxxxxxxxxxx3", "numOrphanedDocs" : 0, "numOwnedDocuments" : 109098088, "ownedSizeBytes" : NumberLong("178157177704"), "orphanedSizeBytes" : 0 }, { "shardName" : "d-xxxxxxxxxxxxxxx4", "numOrphanedDocs" : 0, "numOwnedDocuments" : 382018055, "ownedSizeBytes" : NumberLong("630329790750"), "orphanedSizeBytes" : 0 } ] }この出力から、インスタンスには 4 つのシャードノードがあり、シャード化されたコレクション
<db>.<collection>の合計データ量は約 2051303530231 バイト (833101815840 + 409714745937 + 178157177704 + 630329790750 = 2051303530231)、つまり約 1910.4 GB であると判断できます。 -
過去 1 日間に正常に移行されたデータ量を確認します。
次のクエリを実行します。
pipeline = [ { '$match': { 'what': 'moveChunk.commit', } }, { '$group': { '_id': { 'date': { '$dateToString': { 'format': '%Y-%m-%d', 'date': '$time'} }, }, 'chunks_moved': { '$sum': 1 }, 'docs_moved': { '$sum': '$details.counts.cloned' }, 'bytes_moved': { '$sum': '$details.counts.clonedBytes' }, } }, { '$sort': { '_id.date': -1} }, ] db.getSiblingDB("config").changelog.aggregate(pipeline)出力例:
mongos> db.getSiblingDB("config").changelog.aggregate(pipeline) { "_id" : { "date" : "2024-09-24" }, "chunks_moved" : 91, "docs_moved" : NumberLong(33071040), "bytes_moved" : NumberLong("11532786734") } { "_id" : { "date" : "2024-09-23" }, "chunks_moved" : 294, "docs_moved" : NumberLong(109806635), "bytes_moved" : NumberLong("38294757573") } { "_id" : { "date" : "2024-09-22" }, "chunks_moved" : 737, "docs_moved" : NumberLong(266800041), "bytes_moved" : NumberLong("93047288531") } { "_id" : { "date" : "2024-09-21" }, "chunks_moved" : 1448, "docs_moved" : NumberLong(525308393), "bytes_moved" : NumberLong("183117965820") } { "_id" : { "date" : "2024-09-20" }, "chunks_moved" : 1459, "docs_moved" : NumberLong(530020503), "bytes_moved" : NumberLong("184390749022") } { "_id" : { "date" : "2024-09-19" }, "chunks_moved" : 1478, "docs_moved" : NumberLong(557833705), "bytes_moved" : NumberLong("186910196651") } { "_id" : { "date" : "2024-09-18" }, "chunks_moved" : 1360, "docs_moved" : NumberLong(508484825), "bytes_moved" : NumberLong("173486932689") }この出力は、
2024-09-21に 183117965820 バイト (約 170.5 GB) が移行されたことを示しています。
ステップ 4:タスクの進捗と完了時間の推定
MongoDB 6.0 より前のバージョン
このセクションは、以下のバージョンに適用されます。
-
MongoDB 6.0 より前のバージョンのインスタンス。
-
マイナーエンジンバージョンが 7.0.1 (ベースラインバージョン 6.0.3) より前の MongoDB 6.0 インスタンス。マイナーエンジンバージョンを確認するには、「MongoDB マイナーバージョンガイド」をご参照ください。
正常に移行されたチャンクの数と現在のデータ分散を取得した後、タスク全体の進捗と予想される完了時間を推定します。
シャード追加中に次の理想的な条件を想定します:合計チャンク数は一定で、シャード数は固定 (同時のシャード追加または削除なし)、サービス負荷は安定しており、バランサーパラメーターはデフォルト値を使用します。MongoDB 6.0 より前のバージョンのステップ 3 の例を使用すると、次のことがわかります。
-
5 つのシャードノードがあります。
-
バランサーウィンドウ中に 300 個のチャンクが正常に移行されました。
-
シャード化されたコレクション
<db>.<collection>には、合計 58260 個のチャンクがあります (13630 + 13629 + 13652 + 13630 + 3719 = 58260)。
したがって、以下を計算できます。
-
平衡状態では、各シャードは 11652 個のチャンクを保持する必要があります (58260 ÷ 5 = 11652)。
-
現在の移行レートでは、タスクの完了にはさらに 26.4 日かかります ((11652 – 3719) ÷ 300 ≈ 26.4)。
-
シャード追加タスクは 32% 完了しています (3719 ÷ 11652 = 32%)。
実際のシナリオでは、継続的な書き込みとチャンク分割により、合計チャンク数は増加します。この計算は理想的な条件を想定しており、実際の完了時間は長くなる可能性があります。
MongoDB 6.0 以降のバージョン
このセクションは、以下のバージョンに適用されます。
-
MongoDB 6.0 以降のバージョンのインスタンス。
-
マイナーエンジンバージョンが 7.0.1 (ベースラインバージョン 6.0.3) 以降の MongoDB 6.0 インスタンス。マイナーエンジンバージョンを確認するには、「MongoDB マイナーバージョンガイド」をご参照ください。
シャードクラスターインスタンスにバランシングが必要なコレクションが 1 つしかないと仮定します。MongoDB 6.0 以降のバージョンのステップ 3 の例を使用すると、次のことがわかります。
-
4 つのシャードノードがあります。
-
2024-09-21に、約 170.5 GB (183117965820 バイト) が移行されました。 -
シャード化されたコレクション
<db>.<collection>の合計データ量は約 1910.4 GB (2051303530231 バイト) です。
したがって、以下を計算できます。
-
平衡状態では、各シャードは約 477.6 GB (512825882557.75 バイト) を保持する必要があります。
-
平衡状態に達するために移行が必要な合計データ量は 875559682949 バイト (815.4 GB) で、内訳は次のとおりです。
Shard1 は 320275933282.25 バイト (833101815840 – 512825882557.75) を移行する必要があります。
Shard2 は 103111136620.75 バイト (409714745937 – 512825882557.75) を移行する必要があります。
Shard3 は 334668704853.75 バイト (178157177704 – 512825882557.75) を移行する必要があります。
Shard4 は 117503908192.25 バイト (630329790750 – 512825882557.75) を移行する必要があります。
(320275933282.25 + 103111136620.75 + 334668704853.75 + 117503908192.25 = 875559682949)
-
現在の移行レートでは、約 4.8 日で平衡状態に達します (815.4 GB ÷ 170.5 GB/日 ≈ 4.8 日)。
ステップ 5:タスクフローがブロックされているかの確認 (シャード削除)
シャード削除タスクがブロックされている場合、sh.status() を実行すると、最近の履歴に成功したチャンク移行が表示されず、ターゲットシャードにはまだ移行されていないチャンクが保持されています。これにより、タスクの完了が妨げられ、ApsaraDB for MongoDB コンソールでの他の O&M 操作がブロックされます。
次の例は、このシナリオでの典型的な sh.status() の出力を示しています。
autosplit:
Currently enabled: yes
balancer:
Currently enabled: yes
Currently running: no
Balancer lock taken at Wed Sep 30 2020 02:03:11 GMT+0800 (CST) by ConfigServer:Balancer
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
No recent migrations
databases:
{ "_id" : "report", "primary" : "d-0xixxx", "partitioned" : true }
report.report
shard key: { "GsId" : "hashed" }
unique: false
balancing: true
chunks:
d-0xixxx 9
d-0xixxx 2133
d-0xixxx 2152
d-0xixxx 2116
d-0xixxx 2133
too many chunks to print, use verbose if you want to force print
この問題は、多くの場合、ジャンボチャンクがシャードの削除をブロックするために発生します。次のコマンドを実行してこれを確認します。
db.getSiblingDB("config").chunks.aggregate([{$match: {shard: "d-xxxxxxxxxxxxxx", jumbo:true}},{$group: {_id: "$ns", count: {$sum: 1}}}])
ジャンボチャンクは通常、不適切なシャードキーの設計 (ホットキーなど) が原因で発生します。次のソリューションをお試しください。
-
MongoDB のメジャーバージョンが 4.4 の場合は、refineCollectionShardKey コマンドを使用して、サフィックスを追加してカーディナリティを高め、シャードキーの設計を改善し、ジャンボチャンクを解決します。
-
MongoDB のメジャーバージョンが 5.0 以降の場合は、reshardCollection コマンドを使用して、新しいシャードキーでコレクションを再シャードします。詳細については、「コレクションの再シャード」をご参照ください。
-
一部のビジネスデータを安全に削除できる場合は、ジャンボチャンクからデータを削除します。これにより、サイズが縮小され、バランサーが移行できる通常のチャンクに変換される可能性があります。
-
chunkSizeパラメーターを増やして、ジャンボチャンクの検出基準を変更します。この調整は、Alibaba Cloud のテクニカルサポートエンジニアの支援がある場合にのみ実行してください。
これらの方法で解決しない場合は、チケットを送信してテクニカルサポートにご連絡ください。
追加または削除タスクプロセスの高速化
シャードの追加または削除をより速く完了させるには、次の高速化方法をお試しください。
-
バランサーウィンドウの持続時間を増やします。チャンクの移行は追加の負荷を発生させ、サービスに影響を与える可能性があることに注意してください。調整する前にリスクを評価してください。手順については、「MongoDB バランサーの管理」をご参照ください。
-
`setParameter.chunkMigrationConcurrency` パラメーターを調整して、チャンク移行の同時実行数を変更します。詳細については、「パラメーターチューニングの推奨事項」をご参照ください。
-
オフピーク時間に
moveChunk操作を手動で実行します。詳細については、「sh.moveChunk()」をご参照ください。例:sh.moveChunk("<db>.<collection>", {"<shard_key>": <value>}, "d-xxxxxxxxxxxxx") // 例: sh.moveChunk("records.people", { zipcode: "53187" }, "shard0019") -
チケットを送信して、カーネルパラメーターの調整についてテクニカルサポートにリクエストしてください。