著者は、 Open Internet / Free Speech Fund を選択して、 Write forDOnationsプログラムの一環として寄付を受け取りました。

序章

データベースシャーディングは、通常は同じテーブルまたはコレクションに保持されるレコードを分割し、シャードと呼ばれる複数のマシンに分散するプロセスです。 シャーディングは、新しいシャードとして機能できるマシンを追加することでベースを水平方向にスケーリングできるため、大量のデータを処理する場合に特に役立ちます。

このチュートリアルでは、2つのシャードを使用してシャーディングされたMongoDBクラスターをデプロイする方法を学習します。 このガイドでは、適切なシャードキーを選択する方法と、MongoDBドキュメントがシャード間で正しく均等に分割されているかどうかを確認する方法についても概説します。

警告:このガイドの目的は、MongoDBでシャーディングがどのように機能するかを概説することです。 そのために、開発環境で使用するためにシャードクラスターをすばやくセットアップして実行する方法を示します。 このチュートリアルを完了すると、シャードクラスターが機能しますが、セキュリティ機能は有効になりません。

さらに、MongoDBでは、シャードクラスターのシャードサーバーと構成サーバーをすべて、少なくとも3つのメンバーを持つレプリカセットとしてデプロイすることをお勧めします。 繰り返しになりますが、シャーディングされたクラスターをすばやく稼働させるために、このガイドでは、これらのコンポーネントを単一ノードのレプリカセットとしてデプロイする方法の概要を説明します。

これらの理由により、このセットアップは安全であるとは見なされず、本番環境では使用しないでください。 実稼働環境でシャードクラスターを使用する場合は、内部/メンバーシップ認証に関する公式のMongoDBドキュメントと、MongoDBレプリカセットの構成方法に関するチュートリアルを確認することを強くお勧めします。 Ubuntu20.04で。

前提条件

このチュートリアルに従うには、次のものが必要です。

  • 4つの別々のサーバー。 これらのそれぞれには、sudo特権を持つ通常の非rootユーザーと、UFWで構成されたファイアウォールが必要です。 このチュートリアルは、Ubuntu 20.04を実行している4つのサーバーを使用して検証されました。各サーバーで、Ubuntu20.04のこの初期サーバーセットアップチュートリアルに従ってサーバーを準備できます。
  • 各サーバーにインストールされているMongoDB。 これを設定するには、サーバーごとに Ubuntu20.04にMongoDBをインストールする方法に関するチュートリアルに従ってください。
  • 他の各インスタンスに対してリモートアクセスが有効になっている4つのサーバーすべて。 これを設定するには、 Ubuntu20.04でMongoDBのリモートアクセスを構成する方法に関するチュートリアルに従ってください。 このガイドに従うときは、各サーバーに他の3つのサーバーのIPアドレスが信頼できるIPアドレスとして追加されていることを確認して、すべてのサーバー間のオープンな通信を可能にします。

注:サーバーの構成方法、MongoDBのインストール方法、MongoDBへのリモートアクセスを許可する方法に関するリンクされたチュートリアルはすべて、Ubuntu20.04を参照しています。 このチュートリアルは、基盤となるオペレーティングシステムではなく、MongoDB自体に焦点を当てています。 4つのサーバーのそれぞれが前に概説したように構成されている限り、オペレーティングシステムに関係なく、通常は任意のMongoDBインストールで機能します。

わかりやすくするために、このチュートリアルでは4つのサーバーを次のように参照します。

  • mongo-config 。これは、クラスターの構成サーバーとして機能します。
  • mongo-shard1およびmongo-shard2は、データが実際に配布されるシャードサーバーとして機能します。
  • mongo-router は、mongosインスタンスを実行し、シャードクラスターのクエリルーターとして機能します。

これらのロールとは何か、およびシャーディングされたMongoDBクラスター内でどのように機能するかについての詳細は、MongoDBのシャーディングトポロジについての次のセクションをお読みください。

mongo-config で実行する必要のあるコマンドは、次のように背景が青色になります。

mongo-shard1 で実行する必要のあるコマンドは、背景が赤になります。

mongo-shard2 で実行されるコマンドの背景は、緑色になります。

また、mongo-routerサーバーのコマンドの背景は紫色になります。

MongoDBのシャーディングトポロジを理解する

スタンドアロンのMongoDBデータベースサーバーを使用する場合は、そのインスタンスに接続し、それを使用してデータを直接管理します。 シャーディングされていないレプリカセットでは、クラスターのプライマリメンバーに接続し、そこでデータに加えた変更はすべて、セットのセカンダリメンバーに自動的に引き継がれます。 ただし、シャーディングされたMongoDBクラスターは少し複雑です。

シャーディングは、1つのデータセットのレコードを複数のマシンに分割するため、スケールアウトとも呼ばれる水平スケーリングを支援することを目的としています。 クラスター内のシャードに対してワークロードが大きくなりすぎる場合は、別のシャードを追加して作業の一部を引き受けることにより、データベースをスケールアウトできます。 これは、垂直スケーリング、別名スケールアップとは対照的です。これは、リソースをより大きな、またはより強力なハードウェアに移行することを含みます。

シャーディングされたデータベースアーキテクチャでは、データが物理的に複数のデータベースノードに分割されるため、一部のドキュメントは1つのノードでのみ使用でき、他のドキュメントは別のサーバーに存在します。 特定のインスタンスに接続してデータをクエリすることにした場合、データのサブセットのみを使用できます。 さらに、1つのシャードに保持されているデータを直接変更すると、シャード間に不整合が生じるリスクがあります。

これらのリスクを軽減するために、MongoDBのシャーディングされたクラスターは、次の3つの別個のコンポーネントで構成されています。

  • シャードサーバーは、より大きなデータコレクションのサブセットを格納するために使用される個々のMongoDBインスタンスです。 すべてのシャードサーバーは、常にレプリカセットとしてデプロイする必要があります。 シャーディングされたクラスターには少なくとも1つのシャードが必要ですが、シャーディングから利益を得るには、少なくとも2つ必要です。
  • クラスターのconfigserver は、シャーディングされたクラスターのメタデータと構成設定を格納するMongoDBインスタンスです。 クラスターは、セットアップと管理の目的でこのメタデータを使用します。 シャードサーバーと同様に、このメタデータの高可用性を維持するには、構成サーバーをレプリカセットとして展開する必要があります。
  • mongosは、クエリルーターとして機能する特殊なタイプのMongoDBインスタンスです。 mongosは、クライアントアプリケーションとシャーディングされたクラスター間のプロキシとして機能し、特定のクエリをどこに送信するかを決定します。 すべてのアプリケーション接続は、シャーディングされたクラスター内のクエリルーターを経由するため、構成の複雑さがアプリケーションから隠されます。

MongoDBでのシャーディングはコレクションレベルで行われるため、単一のデータベースにシャーディングされたコレクションとシャーディングされていないコレクションが混在する可能性があります。 シャーディングされたコレクションはパーティション化され、クラスターの複数のシャードに分散されますが、常に1つのシャードがプライマリシャードとして選択されます。 シャーディングされていないコレクションは、このプライマリシャードに完全に保存されます。

すべてのアプリケーション接続はmongosインスタンスを経由する必要があるため、mongosクエリルーターは、すべてのデータを一貫して利用可能にし、個々のシャードに分散させる役割を果たします。

Diagram outlining how to connect to a sharded MongoDB cluster. Applications connect to the mongos query router, which connects to a config server to determine how to query and distribute data to shards. The query router also connects to the shards themselves.

ステップ1—MongoDBConfigサーバーをセットアップする

前提条件を完了すると、4つのMongoDBインストールが4つの別々のサーバーで実行されます。 このステップでは、これらのインスタンスの1つである mongo-config を、テストまたは開発の目的で使用できるレプリカセットに変換します。 また、このMongoDBインスタンスに、シャードクラスターの構成サーバーとして機能できるようにする機能を設定します。

警告:MongoDB 3.6以降、個々のシャードと構成サーバーの両方をレプリカセットとしてデプロイする必要があります。 実稼働環境では、常に3つ以上のメンバーを持つレプリカセットを用意することをお勧めします。 3つ以上のメンバーでレプリカセットを使用すると、データを利用可能で安全な状態に保つのに役立ちますが、シャードアーキテクチャの複雑さも大幅に増します。 ただし、このガイドで概説されているように、ローカル開発には単一ノードのレプリカセットを使用できます。

はじめに前に示した警告を繰り返すために、このガイドでは、シャーディングされたクラスターをすばやく起動して実行する方法の概要を説明します。 したがって、それぞれが単一ノードのレプリカセットで構成されるシャードサーバーと構成サーバーを使用して、シャードクラスターを展開する方法の概要を説明します。 このため、またセキュリティ機能が有効になっていないため、このセットアップは安全ではなく、実稼働環境では使用しないでください。

mongo-config で、お好みのテキストエディターでMongoDB構成ファイルを開きます。 ここでは、nanoを使用します。

  1. sudo nano /etc/mongod.conf

ファイルの下部に#replication:および#sharding:と書かれた行がある構成セクションを見つけます。

/etc/mongod.conf

. . .
#replication:

#sharding:

ポンド記号(#)を削除して、#replication:行のコメントを解除します。 次に、replication:行の下にreplSetNameディレクティブを追加し、その後にMongoDBがレプリカセットを識別するために使用する名前を追加します。 このMongoDBインスタンスを構成サーバーとして機能するレプリカセットとして設定しているため、このガイドではconfigという名前を使用します。

/etc/mongod.conf
. . .
replication:
  replSetName: "config"

#sharding:
. . .

新しいreplSetNameディレクティブの前に2つのスペースがあり、そのconfig値は引用符で囲まれていることに注意してください。 この構文は、構成を正しく読み取るために必要です。

次に、#sharding:行のコメントも解除します。 その後の次の行で、値がconfigsvrclusterRoleディレクティブを追加します。

/etc/mongod.conf
. . .
replication:
  replSetName: "config"

sharding:
  clusterRole: configsvr
. . .

clusterRoleディレクティブは、このサーバーがシャードクラスターの一部になり、構成サーバーの役割を担うことをMongoDBに通知します(configsvr値で示されます)。 繰り返しになりますが、この行の前には必ず2つのスペースを入れてください。

replicationsecurityの両方の行がmongod.confファイルで有効になっている場合、MongoDBではパスワード以外の認証手段も構成する必要がありますキーファイル認証やx.509証明書の設定などの認証。 Ubuntu 20.04でMongoDBを保護する方法チュートリアルに従い、MongoDBインスタンスで認証を有効にした場合、パスワード認証のみが有効になります。

このチュートリアルでは、より高度なセキュリティ対策を設定するのではなく、mongod.confファイルのsecurityブロックを無効にすることをお勧めします。 これを行うには、securityブロックのすべての行をポンド記号でコメントアウトします。

/etc/mongod.conf
. . .

#security:
#  authorization: enabled

. . .

このデータベースをシャーディングやその他のテスト目的の練習にのみ使用することを計画している限り、これによってセキュリティ上のリスクが生じることはありません。 ただし、将来このMongoDBインスタンスを使用して機密データを保存する予定の場合は、これらの行のコメントを解除して、認証を再度有効にしてください

ファイルのこれら2つのセクションを更新した後、ファイルを保存して閉じます。 nanoを使用した場合は、CTRL + XYENTERの順に押すと使用できます。

次に、mongodサービスを再起動します。

  1. sudo systemctl restart mongod

これで、サーバーのレプリケーションが有効になりました。 ただし、MongoDBインスタンスはまだデータを複製していません。 MongoDBシェルを介してレプリケーションを開始する必要があるため、次のコマンドでレプリケーションを開きます。

  1. mongo

MongoDBシェルプロンプトから、次のコマンドを実行してこのレプリカセットを開始します。

  1. rs.initiate()

このコマンドは、MongoDBサーバーによって推測されるデフォルト構成でレプリケーションを開始します。 複数の個別のサーバーで構成されるレプリカセットをセットアップする場合、本番環境に対応したレプリカセットを展開する場合のように、新しいの構成を説明するドキュメントをrs.initiate()メソッドに渡します。レプリカセット。 ただし、このガイドでは、構成サーバーと、それぞれが単一ノードで構成されるシャードサーバーを使用してシャードクラスターをデプロイする方法の概要を説明しているため、このメソッドに引数を渡す必要はありません。

MongoDBは、実行中の構成からレプリカセット名とシャードクラスターでのその役割を自動的に読み取ります。 このメソッドが出力に"ok" : 1を返す場合は、レプリカセットが正常に開始されたことを意味します。

Output
{ "info2" : "no configuration specified. Using a default configuration for the set", . . . "ok" : 1, . . . }

これが当てはまると仮定すると、MongoDBシェルプロンプトが変化して、シェルがrs0レプリカセットのメンバーになっているインスタンスに接続されていることを示します。

この新しいプロンプトの最初の部分は、以前に構成したレプリカセットの名前になります。

このプロンプト例の2番目の部分は、このMongoDBインスタンスがレプリカセットのセカンダリメンバーであることを示していることに注意してください。 通常、レプリカセットが開始されてから、そのメンバーの1つがプライマリメンバーになるまでの間にギャップがあるため、これは予想されることです。

コマンドを実行する場合、またはしばらく待ってからENTERを押すと、プロンプトが更新され、レプリカセットのプライマリメンバーに接続していることが反映されます。

MongoDBシェルで次のコマンドを実行することにより、レプリカセットが正しく構成されていることを確認できます。

  1. rs.status()

これにより、レプリカセットの構成に関する多くの出力が返されますが、いくつかのキーが特に重要です。

Output
{ . . . "set" : "config", . . . "configsvr" : true, "ok" : 1, . . . }

setキーは、レプリカセット名を示します。この例ではconfigです。 configsvrキーは、それがシャードクラスターに設定された構成サーバーのレプリカであるかどうかを示します。この場合はtrueを示しています。 最後に、okフラグの値は1です。これは、レプリカセットが正しく機能していることを意味します。

この手順では、シャードクラスター内の構成サーバーの最初のレプリカセットを構成しました。 次のステップでは、2つの個別のシャードについて同様の構成を実行します。

ステップ2—シャードサーバーレプリカセットの構成

前の手順を完了すると、完全に構成されたレプリカセットが作成され、シャードクラスターの構成サーバーとして機能できるようになります。 このステップでは、mongo-shard1およびmongo-shard2インスタンスもレプリカセットに変換します。 ただし、構成サーバーとして設定するのではなく、シャーディングされたクラスター内の実際のシャードとして機能するように構成します。

これを設定するには、mongo-shard1mongo-shard2の両方の構成ファイルにいくつかの変更を加える必要があります。 ただし、2つの別々のレプリカセットを設定しているため、構成ごとに異なるレプリカセット名が使用されます。

mongo-shard1とmongo-shard2の両方で、お好みのテキストエディターでMongoDB構成ファイルを開きます。

  1. sudo nano /etc/mongod.conf
  1. sudo nano /etc/mongod.conf

ファイルの下部にある#replication:および#sharding:と書かれた行のある構成セクションを見つけます。 繰り返しますが、これらの行はデフォルトで両方のファイルでコメント化されます。

/etc/mongod.conf
#replication:

#sharding:

両方の構成ファイルで、ポンド記号(#)を削除して、#replication:行のコメントを解除します。 次に、replication:行の下にreplSetNameディレクティブを追加し、その後にMongoDBがレプリカセットを識別するために使用する名前を追加します。 これらの例では、 mongo-shard1のレプリカセットにshard1という名前を使用し、mongo-shard2のセットにshard2という名前を使用しています。

/etc/mongod.conf
. . .
replication:
  replSetName: "shard1"

#sharding:
. . .
/etc/mongod.conf
. . .
replication:
  replSetName: "shard2"

#sharding:
. . .

次に、#sharding:行のコメントを解除し、各構成ファイルのその行の下にclusterRoleディレクティブを追加します。 両方のファイルで、clusterRoleディレクティブ値をshardsvrに設定します。 これは、これらのサーバーがシャードとして機能することをそれぞれのMongoDBインスタンスに通知します。

/etc/mongod.conf
. . .
replication:
  replSetName: "shard1"

sharding:
  clusterRole: shardsvr
. . .
/etc/mongod.conf
. . .
replication:
  replSetName: "shard2"

sharding:
  clusterRole: shardsvr
. . .

ファイルのこれら2つのセクションを更新した後、ファイルを保存して閉じます。 次に、両方のサーバーで次のコマンドを発行して、mongodサービスを再起動します。

  1. sudo systemctl restart mongod
  1. sudo systemctl restart mongod

これで、2つのシャードのレプリケーションが有効になりました。 前の手順で設定した構成サーバーと同様に、これらのレプリカセットも、使用する前にMongoDBシェルを介して開始する必要があります。 mongoコマンドを使用して、両方のシャードサーバーでMongoDBシェルを開きます。

  1. mongo
  1. mongo

繰り返しになりますが、このガイドでは、構成サーバーと2つのシャードサーバーを使用してシャードクラスターをデプロイする方法の概要を説明します。これらはすべて、単一ノードのレプリカセットで構成されています。 この種のセットアップは、シャーディングがどのように機能するかをテストおよび概説するのに役立ちますが、は実稼働環境には適していません。

これらのMongoDBインスタンスをシングルノードレプリカセットとして機能するように設定しているため、rs.initiate()メソッドを実行することで、両方のシャードサーバーでレプリケーションを開始できます。

  1. rs.initiate()
  1. rs.initiate()

これらは、デフォルトのレプリカセット構成を使用して、各MongoDBインスタンスでレプリケーションを開始します。 これらのコマンドが出力に"ok" : 1を返す場合は、初期化が成功したことを意味します。

Output
{ "info2" : "no configuration specified. Using a default configuration for the set", . . . "ok" : 1, . . . }
Output
{ "info2" : "no configuration specified. Using a default configuration for the set", . . . "ok" : 1, . . . }

構成サーバーのレプリカセットと同様に、これらの各シャードサーバーは、ほんの数秒後にプライマリメンバーとして選出されます。 プロンプトは最初はSECONDARY>と表示される場合がありますが、しばらくしてからシェルのENTERキーを押すと、プロンプトが変わり、各サーバーがそれぞれのレプリカセットのプライマリインスタンスであることを確認します。 。 2つのシャードのプロンプトは名前だけが異なり、一方はshard1:PRIMARY>で、もう一方はshard2:PRIMARY>です。

両方のMongoDBシェルでrs.status()メソッドを実行することにより、各レプリカセットが正しく構成されていることを確認できます。 まず、mongo-shard1レプリカセットが正しく設定されていることを確認します。

  1. rs.status()

このメソッドの出力に"ok" : 1が含まれている場合は、レプリカセットが正しく機能していることを意味します。

Output
{ . . . "set" : "shard1", . . . "ok" : 1, . . . }

mongo-shard2 で同じコマンドを実行すると、異なるレプリカセット名が表示されますが、それ以外はほぼ同じになります。

  1. rs.status()
Output
{ . . . "set" : "shard2", . . . "ok" : 1, . . . }

これで、mongo-shard1mongo-shard2の両方を単一ノードのレプリカセットとして正常に構成できました。 ただし、この時点では、これら2つのレプリカセットも、前の手順で作成した構成サーバーのレプリカセットも、お互いを認識していません。 次のステップでは、クエリルーターを実行し、それらすべてを接続します。

ステップ3— mongosを実行し、クラスターにシャードを追加する

これまでに構成した3つのレプリカセット(1つの構成サーバーと2つの個別のシャード)が現在実行されていますが、まだシャードクラスターの一部ではありません。 これらのコンポーネントをシャードクラスターの一部として接続するには、もう1つのツール[mongosクエリルーター]が必要です。 これは、構成サーバーとの通信とシャードサーバーの管理を担当します。

4番目で最後のMongoDBサーバーであるmongo-routerを使用して、mongosを実行し、シャードクラスターのクエリルーターとして機能します。 クエリルーターデーモンは、標準のMongoDBインストールの一部として含まれていますが、デフォルトでは有効になっていないため、個別に実行する必要があります。

まず、 mongo-router サーバーに接続し、MongoDBデータベースサービスの実行を停止します。

  1. sudo systemctl stop mongod

このサーバー自体はデータベースとして機能しないため、サーバーが起動するたびにmongodサービスが開始されないようにします。

  1. sudo systemctl disable mongod

次に、mongosを実行し、次のようなコマンドを使用して構成サーバーのレプリカセットに接続します。

  1. mongos --configdb config/mongo_config_ip:27017

このコマンドの接続文字列の最初の部分であるconfigは、前に定義したレプリカの名前です。 異なる場合は必ずこれを変更し、mongo_config_ipmongo-configサーバーのIPアドレスで更新してください。

デフォルトでは、mongosはフォアグラウンドで実行され、ローカルインターフェイスにのみバインドされるため、リモート接続は許可されません。 すべてのサーバー間のトラフィックを制限するファイアウォール設定以外に追加のセキュリティが構成されていないため、これは適切な安全対策です。

注: MongoDBでは、構成サーバーとシャードサーバーが実行されるポートを区別するのが通例であり、27019は構成サーバーのレプリカセットに一般的に使用され、27018は使用されます破片用。 簡単にするために、このガイドでは、このクラスター内のMongoDBインスタンスが実行されているポートを変更していません。 したがって、すべてのレプリカセットは27017のデフォルトポートで実行されています。

前のmongosコマンドは、システムログと同様の形式で詳細な詳細出力を生成します。 最初に、次のようなメッセージが表示されます。

Output
{"t":{"$date":"2021-11-07T15:58:36.278Z"},"s":"W", "c":"SHARDING", "id":24132, "ctx":"main","msg":"Running a sharded cluster with fewer than 3 config servers should only be done for testing purposes and is not recommended for production."} . . .

これは、構成サーバーのレプリカに接続されたクエリルーターが正しく設定され、単一ノードのみで構築されていることに気付いたことを意味します。構成は実稼働環境には推奨されません

注:このようにフォアグラウンドで実行するのがデフォルトの動作ですが、mongosは通常、systemdなどのプロセスを使用してデーモンとして実行されます。

mongosをシステムサービスとして実行することはこのチュートリアルの範囲を超えていますが、公式ドキュメントを読んで、mongosクエリルーターの使用と管理について詳しく学ぶことをお勧めします。 。

これで、以前に構成したシャードをシャードクラスターに追加できます。 mongosがフォアグラウンドで実行されているため、はmongo-routerに接続された別のシェルウィンドウを開きます。 この新しいウィンドウから、MongoDBシェルを開きます。

  1. mongo

このコマンドは、ローカルのMongoDBインスタンスに接続されたMongoDBシェルを開きます。これは、MongoDBサーバーではなく、実行中のmongosクエリルーターです。 プロンプトが変わり、MongoDBシェルの通常の>の代わりにmongos>を読み取ることでこれを示します。

sh.status()メソッドを実行することにより、クエリルーターが構成サーバーに接続されていることを確認できます。

  1. sh.status()

このコマンドは、シャーディングされたクラスターの現在のステータスを返します。 この時点で、shardsキーに接続されているシャードの空のリストが表示されます。

Output
--- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("6187ea2e3d82d39f10f37ea7") } shards: active mongoses: autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: No recent migrations databases: { "_id" : "config", "primary" : "config", "partitioned" : true } . . .

最初のシャードをクラスターに追加するには、次のコマンドを実行します。 この例では、shard1は最初のシャードのレプリカセット名であり、mongo_shard1_ipはそのシャードmongo-shard1が置かれているサーバーのIPアドレスです。ランニング:

  1. sh.addShard("shard1/mongo_shard1_ip:27017")

このコマンドは成功メッセージを返します:

Output
{ "shardAdded" : "shard1", "ok" : 1, "operationTime" : Timestamp(1636301581, 6), "$clusterTime" : { "clusterTime" : Timestamp(1636301581, 6), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } }

続いて、2番目のシャードを追加します。

  1. sh.addShard("shard2/mongo_shard2_ip:27017")

このコマンドのIPアドレスが異なるだけでなく、レプリカセット名も異なることに注意してください。 コマンドは成功メッセージを返します:

Output
{ "shardAdded" : "shard2", "ok" : 1, "operationTime" : Timestamp(1639724738, 6), "$clusterTime" : { "clusterTime" : Timestamp(1639724738, 6), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } } }

sh.status()コマンドを再度発行すると、両方のシャードが正しく追加されていることを確認できます。

  1. sh.status()
Output
--- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("6187ea2e3d82d39f10f37ea7") } shards: { "_id" : "shard1", "host" : "shard1/mongo_shard1_ip:27017", "state" : 1 } { "_id" : "shard2", "host" : "shard2/mongo_shard2_ip:27017", "state" : 1 } active mongoses: "4.4.10" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: No recent migrations databases: { "_id" : "config", "primary" : "config", "partitioned" : true } . . .

これで、2つの稼働中のシャードで構成される完全に機能するシャードクラスターができました。 次のステップでは、新しいデータベースを作成し、データベースのシャーディングを有効にして、コレクション内のデータの分割を開始します。

ステップ4—収集データのパーティション化

シャーディングされたすべてのMongoDBクラスター内の1つのシャードが、クラスターのプライマリシャードとして選出されます。 クラスター内のすべてのシャードに格納されているパーティション化されたデータに加えて、プライマリーシャードはパーティション化されていないデータの格納も担当します。

この時点で、mongosクエリルーターを自由に使用して、一般的な非シャーディングデータベースの場合と同じように、データベース、ドキュメント、およびコレクションを操作できます。 ただし、これ以上設定しないと、クラスターに追加したデータはすべてプライマリシャードにのみ保存されます。 自動的に分割されることはなく、シャーディングが提供するメリットもありません。

シャーディングされたMongoDBクラスターを最大限に活用するには、クラスター内のデータベースに対してシャーディングを有効にする必要があります。 MongoDBデータベースには、シャーディングが有効になっている場合にのみ、シャーディングされたコレクションを含めることができます。

データを分割するときのMongoDBの動作をよりよく理解するには、操作できる一連のドキュメントが必要です。 このガイドでは、世界で最も人口の多い都市のいくつかを表すドキュメントのコレクションを使用します。 例として、次のサンプルドキュメントは東京を表しています。

東京文書
{
    "name": "Tokyo",
    "country": "Japan",
    "continent": "Asia",
    "population": 37.400
}

これらのドキュメントは、populationsというデータベースとcitiesというコレクションに保存されます。

データベースを明示的に作成する前に、データベースのシャーディングを有効にすることができます。 populationsデータベースのシャーディングを有効にするには、次のenableSharding()メソッドを実行します。

  1. sh.enableSharding("populations")

コマンドは成功メッセージを返します:

Output
{ . . . "ok" : 1, . . . }

データベースがパーティショニングを許可するように構成されたので、citiesコレクションのパーティショニングを有効にできます。

MongoDBは、コレクションをシャーディングし、どのドキュメントがどのシャードに保存されるかを決定する2つの方法を提供します。レンジシャーディングハッシュシャーディングです。 このガイドでは、ハッシュシャーディングを実装する方法に焦点を当てています。この方法では、MongoDBは、クラスターのシャードキーとして選択されたフィールドに自動ハッシュインデックスを保持します。 これは、ドキュメントの均等な配布を実現するのに役立ちます。 MongoDBでの遠隔シャーディングについて知りたい場合は、公式ドキュメントを参照してください。

ハッシュベースのシャーディング戦略を実装する場合、適切なシャードキーを選択するのはデータベース管理者の責任です。 不適切に選択されたシャードキーは、シャーディングから得られる可能性のある多くの利点を軽減する可能性があります。

MongoDBでは、シャードキーとして適切に機能するドキュメントフィールドは、次の原則に従う必要があります。

  • 選択するフィールドは、カーディナリティが高い必要があります。つまり、多くの可能な値を持つことができます。 コレクションに追加されたすべてのドキュメントは、常に単一のシャードに保存されるため、シャードキーとして選択されたフィールドに可能な値が少ない場合、クラスターにシャードを追加してもパフォーマンスは向上しません。 populationsデータベースの例を考えると、continentフィールドにはいくつかの可能な値しか含めることができないため、適切なシャードキーにはなりません。
  • シャードキーは、重複する値の頻度が低い必要があります。 ドキュメントの大部分がシャードキーとして使用されるフィールドの値が重複している場合、一部のシャードが他のシャードよりも多くのデータを格納するために使用される可能性があります。 コレクション全体でシャードキーの値が均等に分散されているほど、優れています。
  • シャードキーはクエリを容易にする必要があります。 たとえば、クエリフィルタとして頻繁に使用されるフィールドは、シャードキーに適しています。 シャードクラスターでは、クエリルーターは単一のシャードを使用して、クエリにシャードキーが含まれている場合にのみクエリ結果を返します。 それ以外の場合、返されたドキュメントが単一のシャードからのものであっても、クエリは評価のためにすべてのシャードにブロードキャストされます。 したがって、populationフィールドは、クエリの大部分が正確な母集団値によるフィルタリングを伴う可能性が低いため、最適なキーではありません。

このガイドで使用されているサンプルデータの場合、country名前フィールドは、フィルタークエリで頻繁に使用される可能性が高いすべてのフィールドの中で最もカーディナリティが高いため、クラスターのシャードキーに適しています。

次のshardCollection()メソッドを実行して、citiesコレクション(まだ作成されていません)をcountryフィールドをシャードキーとしてパーティション分割します。

  1. sh.shardCollection("populations.cities", { "country": "hashed" })

このコマンドの最初の部分はpopulationsデータベースのcitiesコレクションを参照し、2番目の部分はhashedパーティションを使用してシャードキーとしてcountryを選択します方法。

コマンドは成功メッセージを返します:

Output
{ "collectionsharded" : "populations.cities", "collectionUUID" : UUID("03823afb-923b-4cd0-8923-75540f33f07d"), "ok" : 1, . . . }

これで、いくつかのサンプルドキュメントをシャーディングされたクラスターに挿入できます。 まず、populationsデータベースに切り替えます。

  1. use populations

次に、次のinsertManyコマンドを使用して、20個のサンプルドキュメントを挿入します。

  1. db.cities.insertMany([
  2. {"name": "Seoul", "country": "South Korea", "continent": "Asia", "population": 25.674 },
  3. {"name": "Mumbai", "country": "India", "continent": "Asia", "population": 19.980 },
  4. {"name": "Lagos", "country": "Nigeria", "continent": "Africa", "population": 13.463 },
  5. {"name": "Beijing", "country": "China", "continent": "Asia", "population": 19.618 },
  6. {"name": "Shanghai", "country": "China", "continent": "Asia", "population": 25.582 },
  7. {"name": "Osaka", "country": "Japan", "continent": "Asia", "population": 19.281 },
  8. {"name": "Cairo", "country": "Egypt", "continent": "Africa", "population": 20.076 },
  9. {"name": "Tokyo", "country": "Japan", "continent": "Asia", "population": 37.400 },
  10. {"name": "Karachi", "country": "Pakistan", "continent": "Asia", "population": 15.400 },
  11. {"name": "Dhaka", "country": "Bangladesh", "continent": "Asia", "population": 19.578 },
  12. {"name": "Rio de Janeiro", "country": "Brazil", "continent": "South America", "population": 13.293 },
  13. {"name": "São Paulo", "country": "Brazil", "continent": "South America", "population": 21.650 },
  14. {"name": "Mexico City", "country": "Mexico", "continent": "North America", "population": 21.581 },
  15. {"name": "Delhi", "country": "India", "continent": "Asia", "population": 28.514 },
  16. {"name": "Buenos Aires", "country": "Argentina", "continent": "South America", "population": 14.967 },
  17. {"name": "Kolkata", "country": "India", "continent": "Asia", "population": 14.681 },
  18. {"name": "New York", "country": "United States", "continent": "North America", "population": 18.819 },
  19. {"name": "Manila", "country": "Philippines", "continent": "Asia", "population": 13.482 },
  20. {"name": "Chongqing", "country": "China", "continent": "Asia", "population": 14.838 },
  21. {"name": "Istanbul", "country": "Turkey", "continent": "Europe", "population": 14.751 }
  22. ])

ユーザーの観点からは、シャーディングされたクラスターは通常のMongoDBデータベースのように動作するため、出力は通常のMongoDB出力と同様になります。

Output
{ "acknowledged" : true, "insertedIds" : [ ObjectId("61880330754a281b83525a9b"), ObjectId("61880330754a281b83525a9c"), ObjectId("61880330754a281b83525a9d"), ObjectId("61880330754a281b83525a9e"), ObjectId("61880330754a281b83525a9f"), ObjectId("61880330754a281b83525aa0"), ObjectId("61880330754a281b83525aa1"), ObjectId("61880330754a281b83525aa2"), ObjectId("61880330754a281b83525aa3"), ObjectId("61880330754a281b83525aa4"), ObjectId("61880330754a281b83525aa5"), ObjectId("61880330754a281b83525aa6"), ObjectId("61880330754a281b83525aa7"), ObjectId("61880330754a281b83525aa8"), ObjectId("61880330754a281b83525aa9"), ObjectId("61880330754a281b83525aaa"), ObjectId("61880330754a281b83525aab"), ObjectId("61880330754a281b83525aac"), ObjectId("61880330754a281b83525aad"), ObjectId("61880330754a281b83525aae") ] }

ただし、内部的には、MongoDBはシャーディングされたノード全体にドキュメントを配布しました。

getShardDistribution()メソッドを使用して、データがシャード全体にどのように分散されたかに関する情報にアクセスできます。

  1. db.cities.getShardDistribution()

このメソッドの出力は、クラスターの一部であるすべてのシャードの統計を提供します。

Output
Shard shard2 at shard2/mongo_shard2_ip:27017 data : 943B docs : 9 chunks : 2 estimated data per chunk : 471B estimated docs per chunk : 4 Shard shard1 at shard1/mongo_shard1_ip:27017 data : 1KiB docs : 11 chunks : 2 estimated data per chunk : 567B estimated docs per chunk : 5 Totals data : 2KiB docs : 20 chunks : 4 Shard shard2 contains 45.4% data, 45% docs in cluster, avg obj size on shard : 104B Shard shard1 contains 54.59% data, 55% docs in cluster, avg obj size on shard : 103B

この出力は、countryフィールドの自動ハッシュ戦略により、2つのシャード間でほぼ均等に分散されたことを示しています。

これで、完全に機能するシャードクラスターを構成し、複数のシャードに自動的に分割されたデータを挿入しました。 次のステップでは、クエリを実行するときにシャードの使用状況を監視する方法を学習します。

ステップ5—シャードの使用状況を分析する

シャーディングは、データベースシステムのパフォーマンスをスケーリングするために使用されるため、データベースクエリをサポートするために効率的に使用される場合に最適に機能します。 データベースへのクエリのほとんどを実行するためにクラスター内のすべてのシャードをスキャンする必要がある場合、システムの複雑さが増すと、シャーディングの利点が失われます。

この手順では、クエリが単一のシャードのみを使用するように最適化されているかどうか、または結果を取得するために複数のシャードにまたがっているかどうかを確認することに焦点を当てます。

citiesコレクション内のすべてのドキュメントを選択することから始めます。 すべてのドキュメントを取得する必要があるため、クエリを実行するにはすべてのシャードを使用する必要があります。

  1. db.cities.find()

当然のことながら、クエリはすべての都市を返します。 今度はexplain()メソッドを最後に付けて、クエリを再実行します。

  1. db.cities.find().explain()

長い出力は、クエリがどのように実行されたかについての詳細を提供します。

Output
{ "queryPlanner" : { "mongosPlannerVersion" : 1, "winningPlan" : { "stage" : "SHARD_MERGE", "shards" : [ { "shardName" : "shard1", . . . }, { "shardName" : "shard2", . . . } ] } }, . . .

勝利プランはSHARD_MERGE戦略を参照していることに注意してください。これは、クエリを解決するために複数のシャードが使用されたことを意味します。 shardsキーで、MongoDBは評価に参加しているシャードのリストを返します。 この場合、このリストにはクラスターの両方のシャードが含まれます。

次に、選択したシャードキーではないcontinentフィールドに対してクエリを実行した場合に、結果が異なるかどうかをテストします。

  1. db.cities.find({"continent": "Europe"}).explain()

今回は、MongoDBもクエリを満たすために両方のシャードを使用する必要がありました。 データベースには、どのシャードにヨーロッパの都市のドキュメントが含まれているかを知る方法がありませんでした。

Output
{ "queryPlanner" : { "mongosPlannerVersion" : 1, "winningPlan" : { "stage" : "SHARD_MERGE", . . . } }, . . .

シャードキーに対してフィルタリングする場合、結果は異なるはずです。 以前にシャードキーとして選択したcountryフィールドを使用して、日本からのみ都市をフィルタリングしてみてください。

  1. db.cities.find({"country": "Japan"}).explain()
Output
{ "queryPlanner" : { "mongosPlannerVersion" : 1, "winningPlan" : { "stage" : "SINGLE_SHARD", "shards" : [ { "shardName" : "shard1", . . . } . . .

今回、MongoDBは別のクエリ戦略を使用しました:SHARD_MERGEの代わりにSINGLE_SHARD。 これは、クエリを満たすために必要なシャードが1つだけであることを意味します。 shardsキーでは、単一のシャードのみが言及されます。 この例では、日本のドキュメントはクラスターの最初のシャードに保存されています。

クエリカーソルのexplain機能を使用すると、実行しているクエリが1つまたは複数のシャードにまたがっているかどうかを確認できます。 次に、すべてのシャードに一度に到達することで、クエリがクラスターをオーバーロードするかどうかを判断するのにも役立ちます。 この方法を(シャードキー選択の経験則と一緒に)使用して、パフォーマンスが最も向上するシャードキーを選択できます。

結論

シャーディングは、大規模なデータクラスターのパフォーマンスとスケーラビリティを向上させるための戦略として広く使用されています。 レプリケーションと組み合わせると、シャーディングによって可用性とデータセキュリティが向上する可能性もあります。 シャーディングは、MongoDBの水平スケーリングのコア手段でもあり、データベースをより大きく強力なサーバーに移行する代わりに、クラスターにノードを追加することでデータベースクラスターのパフォーマンスを拡張できます。

このチュートリアルを完了することで、MongoDBでシャーディングがどのように機能するか、構成サーバーと個々のシャードを構成する方法、およびそれらを接続してシャードクラスターを形成する方法を学習しました。 mongosクエリルーターを使用して、シャードの管理、データパーティショニングの導入、データベースに対するクエリの実行、およびシャーディングメトリックの監視を行いました。

この戦略には多くの利点がありますが、複数のレプリカセットを管理する必要があるなどの管理上の課題や、より複雑なセキュリティの考慮事項もあります。 開発環境外でのシャーディングとシャーディングされたクラスターの実行の詳細については、このテーマに関する公式のMongoDBドキュメントを確認することをお勧めします。 それ以外の場合は、MongoDBを使用してデータを管理する方法に関するシリーズの他のチュートリアルを確認することをお勧めします。