MongoDBの・ベスト・プラクティス・回数許さ分析

背景

一般的には、遅延のほかに起因する二次ノードのクエリ二不正確なデータは、カウントの精度についての質問に、MongoDB4.0公式文書で非常に多くの言葉がある以外の原因となります
)シャードクラスタ、db.collection.count(オンにすることなく、 predicateA CAN ANクエリで結果が不正確またはIFはiforphanedドキュメントをCOUNTチャンクに存在する移行の進行状況である。
このような状況を避けるために、シャードクラスタ上で、使用db.collection.aggregate()メソッド

而MongoDB3.6官方文档却是这么描述的
シャードクラスタ上で、db.collection.count()チャンクの移行が進行中である場合に孤立した文書が存在する場合、または不正確な数になります。
このような状況を回避するには、シャードクラスタ上で、db.collection.aggregate()メソッドを使用します

言い換えれば、MongoDB4.0クラスタの断片化モードで、述語条件カウントせずに、完全なテーブルのために帰国すると、次の2つのシナリオを含む正確な動作、ではありません。MongoDB4.0以前のバージョンでは、さえ述語条件なしで、カウント値は、次の2つのシナリオで許可されていません。
1が孤立するドキュメントである
クラスタの継続的な移動チャンク動作における2 Mongoの断片
両方のシナリオについては、この論文では、原因を分析し、回避措置がカウントすることはできません

孤立した文書は、カウントをリードすることはできません

孤立した文書の定義と原因

単離された文書は、ソース・チャンクは、レコードのこの部分は、ソースとターゲット側の両方に存在しながら、によって引き起こされる障害またはクリーニングマイグレーション障害による移動チャンク異常シャットダウン時に起因する処理を移行し、そして内Mongoの断片化されたクラスタの定義にありますドキュメントはのみチャンクとシャードに属している必要があります。
もちろん、分離をもたらすことができる文書が単離された文書が大きすぎる場合、それは追加のディスク・ストレージ・リソースを占有することになる、カウントすることはできません。

一般的には、次の手順についての動作をmovechunk

  • ソースへロードバランサスライスコマンドはmovechunkを送信します
  • スライスが内部にソースデータブロックの移行を開始、移行の持続時間は、ソース端子が読み取りおよび書き込みを含め、すべてのアクセス要求を受信します
  • インデックスに対応するターゲット側のセットアップをスライス
  • のコピー元チャンクの先頭から引き継いだターゲットスライスデータの終了
  • 文書の最後のチャンクを受信した後目標端末は、目標スライス開放端は、移行チャンク中に生成デルタ同期プロセスのソースデータを受信する場合
  • すべてのデータはまた、増分同期が完了したとき、スライスに接続されたソース端子は、メタデータデータベースの設定を変更し始める、すなわちチャンクがフラグメント属する変更
  • あなたが設定メタデータを変更したら、元のスライスは、データチャンクの移行を開始する前に削除します
    move_chunk

ソースプロセスからエンド・コピー・データへの本当の目標を達成するために設計されたMongoDBは、移動効率に残っているデータの断片化のソースをクリーンアップする最後のステップを1つのチャンクことではなく、対価のうち一つだけ移行され、シリアルです操作は非同期で、設定は、メタデータを修正した後、すぐに移行の次のチャンクを入力することができたときに言うことです、ソースは、完全なフラグメンテーションクリーニングを待つ必要はありません。
プライマリノードのクラッシュ時には、分離された文書を作成する場合は、それはクリーニングの遅い蓄積のために引き起こされる可能性がいくつかのシナリオでは、キュー内のデータのクリーンなソース古いチャンクをスライス。

シミュレーションと説明

チャンクの移行プロセスからわかるように、移行プロセスが失敗した場合、我々はまだ、それは理論的には、ターゲット側のデータをクリーンアップするかどうか分からない、ターゲットスライスに孤立した文書を引き起こす可能性がありますが、movechunkシリアル処理ので、せいぜい、あったとしてもチャンク問題のブロック、最後のステップは、データ・ソースに障害が発生した古いチャンクをクリーンアップする場合だが、間違いなくソースで分離された文書につながる、と最悪の場合のチャンクを孤立多数の文書を生成することができます。

だからクラスタをスライスするために、既存のシャードの場合のように重いmovechunk、中にマスターノードのmongodを殺すためにプロセスを強制別のシャードを追加する必要があり、孤立した文書は非常に簡単ですシミュレートするために、そして必然的に必要とします操作多数のmovechunk、このように本明細書中で使用されます。

//添加sharding前,确认sh.isBalancerRunning()为false,因为movechunk期间count本来也不准
mongos> db.user.count({_id:{$gte:0}})
43937296
mongos> db.user.count()
43937296
//添加分片过程中kill -9 mongod进程,重新拉起各个分片,
mongos> db.user.count({_id:{$gte:0}})
43937296
mongos> db.user.count()
51028273
mongos> db.user.aggregate([{ $count:"myCount"}])
{ "myCount" : 43937296 }

分散クラスタモードでメタデータ・テーブルおよび情報のため、この場合に、計数結果の値を直接チャンク、述語条件なしにのみフル・テーブル・カウントが現象をもたらすことが許可され、上から見ることができますすなわち、チャンクテーブルのアクセスの各スライスカウント値を得るために一つ一つであり、その文書の存在による戻り蓄積を行い、単離された返された結果を生じさせることは、正確な結果よりも大きいです。文書内の最後の場合は7090977の単離を生じました。

孤立した書類の方法を避け、排除

一方、孤立して作成されたドキュメントの数を減らし、デフォルトでは、ソースデータの断片化をクリーンアップすることは、非同期呼び出しですが、また、多くても1つのチャンクで、場合は、プライマリノードのクラッシュを設定した後、つまり、同期呼び出しに設定するコマンドすることができますそれは孤立生産が、お勧めできません、非常に有意義ではないかもしれません。設定方法

use config
db.settings.update( { "_id" : "balancer" },{ $set : { "_waitForDelete" : true } },{ upsert : true })

生成された文書は、単離された場合、以下のように、別の観点からは、MongoDBのドキュメントは、各ノードのシャーディング上で実行される方法のすべての単離されたフラグメントを、明確な提供します

var nextKey = { };
var result;
while ( nextKey != null ) {
  result = db.adminCommand( { cleanupOrphaned: "test.user", startingFromKey: nextKey } );
  if (result.ok != 1)
   print("Unable to complete at this time: failure or timeout.")
  printjson(result);
  nextKey = result.stoppedAtKey;
}

移動チャンクの間にカウントすることはできません

症状

またはログのmongod sh.isBalancerRunningによって確認することができる()コマンド、移動チャンクステージのテーブルは、
観察の便宜のために、我々は、すなわちチャンクにスライスデータ一旦終了チャンクエンドポイントの直後に削除移行元、1に設定さ_waitForDeleteう移行は、結果は、急速な成長の最初のプロセスのカウント値を観察し、還元の比較的遅いプロセスであることができ、
各チャンクの移行サイクルプロセスをOFFした後sh.isBalancerRunning()まで、安定した正確な値に。

原因分析

  • 移動チャンクが完了していない場合、プロセス移動チャンクでは、次いで、ソースとターゲット側の断片にデータが存在します
  • 数無意味な単語の用語は、そのフラグメントデータ上で実行統計に含まれている送信元と送信先の端に移動のチャンクを完了していないときは、値の上昇があるだろう結果が表示されます
  • コピーデータが終了した後と、この段階では、値をカウントして、ソースデータスライススタートクリーニングにメタデータを修正することが徐々に低下しています
  • 値低減処理が比較的遅い、それはコピーデータよりも長いを過ごすために起因するクリーンアップタイムスライスデータソースポイントにする必要があります数えます

メタデータを変更した後、プロセスの移動チャンクでは、非動作回数場合、一般的なクエリは確かにコピーデータmovechunkソースは、すべてのアクセス要求を受信中に、移行プロセスは、以前の分析によるので、このようなエラーを容認することはできませんソースデータを削除する時に、ターゲット側は、すべてのアクセス要求を受信します。言い換えれば、一般的なクエリは、その結果が正確であるので、設定サーバーのメタデータに完全に準拠して、唯一のシャードに所属し、所属する実際のクエリチャンクを判断する必要があります。

MongoDB4.0以前のバージョン場合は、偶数値を結果の述語条件が許可されると、操作をカウントします。これは、異なる以前のバージョン4.0と共通クエリ内の述語条件にカウント動作原理ので、それはチャンクのトラバーサルをチェックするために行かない本当に唯一のシャード、バージョン4.0以降に属しており、その原理は、一般的なクエリと同じです、値が許可されていない結果の状況に終止符を打ちます。

バージョン4.0は、述語条件なしのカウントの正確さを保証するものではありませんので、このカウントシナリオでは、ビジネスのほとんどは非常に正確である必要はありませんので、デザイン哲学の分析から、それは、パフォーマンスと効率の妥協の一種と見なすことができます結果をカウントし、「速い数」という概念をより重視、つまり、データを横断せずにメタデータレベルから直接値を返します。私たちは、これはバグであると考えることはできません、もちろん、あなたが正確なカウント値を必要とするだけでなく、集計方法に置き換えることができ、ポイントを最適化することがあれば、カウント方法のちょうど2つの種類のかもしれ誤解を招く、コマンド表示と互換性がありません。

改善点とその回避策

効率と精度を求めて1ながら、ロードバランシングがウィンドウが以外移動チャンク禁止され、窓を設けることができる
シーンデータの精度2は、COUNTの代わりdb.collection.aggregate()メソッドを使用して強調
MongoのあろうCOUNT述語条件で動作する。3 4.0以上にアップグレード
孤立した文書が多数の場合は4、分離された文書は、クリーンアップを行います

おすすめ

転載: yq.aliyun.com/articles/704434