MongoDBでシャーディングを使用する方法
著者は、 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
クエリルーターは、すべてのデータを一貫して利用可能にし、個々のシャードに分散させる役割を果たします。
ステップ1—MongoDBConfigサーバーをセットアップする
前提条件を完了すると、4つのMongoDBインストールが4つの別々のサーバーで実行されます。 このステップでは、これらのインスタンスの1つである mongo-config を、テストまたは開発の目的で使用できるレプリカセットに変換します。 また、このMongoDBインスタンスに、シャードクラスターの構成サーバーとして機能できるようにする機能を設定します。
警告:MongoDB 3.6以降、個々のシャードと構成サーバーの両方をレプリカセットとしてデプロイする必要があります。 実稼働環境では、常に3つ以上のメンバーを持つレプリカセットを用意することをお勧めします。 3つ以上のメンバーでレプリカセットを使用すると、データを利用可能で安全な状態に保つのに役立ちますが、シャードアーキテクチャの複雑さも大幅に増します。 ただし、このガイドで概説されているように、ローカル開発にはシングルノードレプリカセットを使用できます。
はじめに前に示した警告を繰り返すために、このガイドでは、シャーディングされたクラスターをすばやく起動して実行する方法の概要を説明します。 したがって、それぞれが単一ノードのレプリカセットで構成されるシャードサーバーと構成サーバーを使用してシャードクラスターを展開する方法の概要を説明します。 このため、またセキュリティ機能が有効になっていないため、このセットアップは安全ではなく、実稼働環境では使用しないでください。
mongo-config で、お好みのテキストエディターでMongoDB構成ファイルを開きます。 ここでは、nano
を使用します。
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:
行のコメントも解除します。 その後の次の行で、値がconfigsvr
のclusterRole
ディレクティブを追加します。
/etc/mongod.conf
. . . replication: replSetName: "config" sharding: clusterRole: configsvr . . .
clusterRole
ディレクティブは、このサーバーがシャードクラスターの一部になり、構成サーバーの役割を担うことをMongoDBに通知します(configsvr
値で示されます)。 繰り返しになりますが、この行の前には必ず2つのスペースを入れてください。
注:replication
とsecurity
の両方の行がmongod.conf
ファイルで有効になっている場合、MongoDBではパスワード以外の認証手段も構成する必要がありますキーファイル認証やx.509証明書の設定などの認証。 Ubuntu 20.04でMongoDBを保護する方法チュートリアルに従い、MongoDBインスタンスで認証を有効にした場合、パスワード認証のみが有効になります。
このチュートリアルでは、より高度なセキュリティ対策を設定するのではなく、mongod.conf
ファイルのsecurity
ブロックを無効にすることをお勧めします。 これを行うには、security
ブロックのすべての行をポンド記号でコメントアウトします。
/etc/mongod.conf
. . . #security: # authorization: enabled . . .
このデータベースをシャーディングまたはその他のテスト目的の練習にのみ使用することを計画している限り、これによってセキュリティ上のリスクが生じることはありません。 ただし、将来このMongoDBインスタンスを使用して機密データを保存する予定の場合は、これらの行のコメントを解除して、認証を再度有効にしてください。
ファイルのこれら2つのセクションを更新した後、ファイルを保存して閉じます。 nano
を使用した場合は、CTRL + X
、Y
、ENTER
の順に押すと使用できます。
次に、mongod
サービスを再起動します。
sudo systemctl restart mongod
これで、サーバーのレプリケーションが有効になりました。 ただし、MongoDBインスタンスはまだデータを複製していません。 MongoDBシェルを介してレプリケーションを開始する必要があるため、次のコマンドでレプリケーションを開きます。
mongo
MongoDBシェルプロンプトから、次のコマンドを実行してこのレプリカセットを開始します。
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シェルで次のコマンドを実行することにより、レプリカセットが正しく構成されていることを確認できます。
rs.status()
これにより、レプリカセットの構成に関する多くの出力が返されますが、いくつかのキーが特に重要です。
Output{ . . . "set" : "config", . . . "configsvr" : true, "ok" : 1, . . . }
set
キーは、レプリカセット名を示します。この例ではconfig
です。 configsvr
キーは、それがシャードクラスターに設定された構成サーバーのレプリカであるかどうかを示します。この場合はtrue
を示しています。 最後に、ok
フラグの値は1
です。これは、レプリカセットが正しく機能していることを意味します。
この手順では、シャードクラスター内の構成サーバーの最初のレプリカセットを構成しました。 次のステップでは、2つの個別のシャードについて同様の構成を実行します。
ステップ2—シャードサーバーレプリカセットの構成
前の手順を完了すると、シャードクラスターの構成サーバーとして機能できる完全に構成されたレプリカセットが作成されます。 このステップでは、mongo-shard1およびmongo-shard2インスタンスもレプリカセットに変換します。 ただし、構成サーバーとして設定するのではなく、シャーディングされたクラスター内の実際のシャードとして機能するように構成します。
これを設定するには、mongo-shard1とmongo-shard2の両方の構成ファイルにいくつかの変更を加える必要があります。 ただし、2つの別々のレプリカセットを設定しているため、構成ごとに異なるレプリカセット名が使用されます。
mongo-shard1とmongo-shard2の両方で、お好みのテキストエディターでMongoDB構成ファイルを開きます。
sudo nano /etc/mongod.conf
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
サービスを再起動します。
sudo systemctl restart mongod
sudo systemctl restart mongod
これで、2つのシャードのレプリケーションが有効になりました。 前の手順で設定した構成サーバーと同様に、これらのレプリカセットも、使用する前にMongoDBシェルを介して開始する必要があります。 mongo
コマンドを使用して、両方のシャードサーバーでMongoDBシェルを開きます。
mongo
mongo
繰り返しになりますが、このガイドでは、構成サーバーと2つのシャードサーバーを備えたシャードクラスターをデプロイする方法の概要を説明します。これらはすべて、単一ノードのレプリカセットで構成されています。 この種のセットアップは、シャーディングがどのように機能するかをテストおよび概説するのに役立ちますが、は実稼働環境には適していません。
これらのMongoDBインスタンスをシングルノードレプリカセットとして機能するように設定しているため、rs.initiate()
メソッドを実行することで、両方のシャードサーバーでレプリケーションを開始できます。
rs.initiate()
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レプリカセットが正しく設定されていることを確認します。
rs.status()
このメソッドの出力に"ok" : 1
が含まれている場合は、レプリカセットが正しく機能していることを意味します。
Output{ . . . "set" : "shard1", . . . "ok" : 1, . . . }
mongo-shard2 で同じコマンドを実行すると、異なるレプリカセット名が表示されますが、それ以外はほぼ同じになります。
rs.status()
Output{ . . . "set" : "shard2", . . . "ok" : 1, . . . }
これで、mongo-shard1とmongo-shard2の両方を単一ノードのレプリカセットとして正常に構成できました。 ただし、この時点では、これら2つのレプリカセットも、前の手順で作成した構成サーバーのレプリカセットも、お互いを認識していません。 次のステップでは、クエリルーターを実行し、それらすべてを接続します。
ステップ3— mongos
を実行し、クラスターにシャードを追加する
これまでに構成した3つのレプリカセット(1つの構成サーバーと2つの個別のシャード)が現在実行されていますが、まだシャードクラスターの一部ではありません。 これらのコンポーネントをシャードクラスターの一部として接続するには、もう1つのツール[mongos
クエリルーター]が必要です。 これは、構成サーバーとの通信とシャードサーバーの管理を担当します。
4番目で最後のMongoDBサーバーであるmongo-routerを使用して、mongos
を実行し、シャードクラスターのクエリルーターとして機能します。 クエリルーターデーモンは、標準のMongoDBインストールの一部として含まれていますが、デフォルトでは有効になっていないため、個別に実行する必要があります。
まず、 mongo-router サーバーに接続し、MongoDBデータベースサービスの実行を停止します。
sudo systemctl stop mongod
このサーバー自体はデータベースとして機能しないため、サーバーが起動するたびにmongod
サービスが開始されないようにします。
sudo systemctl disable mongod
次に、mongos
を実行し、次のようなコマンドを使用して構成サーバーのレプリカセットに接続します。
mongos --configdb config/mongo_config_ip:27017
このコマンドの接続文字列の最初の部分であるconfig
は、前に定義したレプリカの名前です。 異なる場合は必ずこれを変更し、mongo_config_ip
をmongo-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シェルを開きます。
mongo
このコマンドは、ローカルのMongoDBインスタンスに接続されたMongoDBシェルを開きます。これは、MongoDBサーバーではなく、実行中のmongos
クエリルーターです。 プロンプトが変わり、MongoDBシェルの通常の>
の代わりにmongos>
を読み取ることでこれを示します。
sh.status()
メソッドを実行することにより、クエリルーターが構成サーバーに接続されていることを確認できます。
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アドレスです。ランニング:
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番目のシャードを追加します。
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()
コマンドを再度発行すると、両方のシャードが正しく追加されていることを確認できます。
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()
メソッドを実行します。
sh.enableSharding("populations")
コマンドは成功メッセージを返します:
Output{ . . . "ok" : 1, . . . }
データベースがパーティショニングを許可するように構成されたので、cities
コレクションのパーティショニングを有効にできます。
MongoDBは、コレクションをシャーディングし、どのドキュメントがどのシャードに保存されるかを決定する2つの方法を提供します。レンジシャーディングとハッシュシャーディングです。 このガイドでは、ハッシュシャーディングを実装する方法に焦点を当てています。この場合、MongoDBは、クラスターのシャードキーとして選択されたフィールドに自動ハッシュインデックスを保持します。 これは、ドキュメントの均等な配布を実現するのに役立ちます。 MongoDBでの遠隔シャーディングについて知りたい場合は、公式ドキュメントを参照してください。
ハッシュベースのシャーディング戦略を実装する場合、適切なシャードキーを選択するのはデータベース管理者の責任です。 不適切に選択されたシャードキーは、シャーディングから得られる可能性のある多くの利点を軽減する可能性があります。
MongoDBでは、シャードキーとして適切に機能するドキュメントフィールドは、次の原則に従う必要があります。
- 選択するフィールドは、カーディナリティが高い必要があります。つまり、多くの可能な値を持つことができます。 コレクションに追加されたすべてのドキュメントは常に単一のシャードに保存されるため、シャードキーとして選択されたフィールドに可能な値が少ない場合、クラスターにシャードを追加してもパフォーマンスは向上しません。
populations
データベースの例を考えると、continent
フィールドにはいくつかの可能な値しか含めることができないため、適切なシャードキーにはなりません。 - シャードキーは、重複する値の頻度が低い必要があります。 ドキュメントの大部分がシャードキーとして使用されるフィールドの値が重複している場合、一部のシャードが他のシャードよりも多くのデータを格納するために使用される可能性があります。 コレクション全体でシャードキーの値が均等に分散されているほど、優れています。
- シャードキーはクエリを容易にする必要があります。 たとえば、クエリフィルタとして頻繁に使用されるフィールドは、シャードキーに適しています。 シャードクラスターでは、クエリルーターは単一のシャードを使用して、クエリにシャードキーが含まれている場合にのみクエリ結果を返します。 それ以外の場合、返されたドキュメントが単一のシャードからのものであっても、クエリは評価のためにすべてのシャードにブロードキャストされます。 したがって、
population
フィールドは、クエリの大部分が正確な母集団値によるフィルタリングを伴う可能性が低いため、最適なキーではありません。
このガイドで使用されているサンプルデータの場合、country
名前フィールドは、フィルタークエリで頻繁に使用される可能性が高いすべてのフィールドの中で最もカーディナリティが高いため、クラスターのシャードキーに適しています。
次のshardCollection()
メソッドを実行して、cities
コレクション(まだ作成されていません)をcountry
フィールドをシャードキーとしてパーティション分割します。
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
データベースに切り替えます。
use populations
次に、次のinsertMany
コマンドを使用して、20個のサンプルドキュメントを挿入します。
db.cities.insertMany([ {"name": "Seoul", "country": "South Korea", "continent": "Asia", "population": 25.674 }, {"name": "Mumbai", "country": "India", "continent": "Asia", "population": 19.980 }, {"name": "Lagos", "country": "Nigeria", "continent": "Africa", "population": 13.463 }, {"name": "Beijing", "country": "China", "continent": "Asia", "population": 19.618 }, {"name": "Shanghai", "country": "China", "continent": "Asia", "population": 25.582 }, {"name": "Osaka", "country": "Japan", "continent": "Asia", "population": 19.281 }, {"name": "Cairo", "country": "Egypt", "continent": "Africa", "population": 20.076 }, {"name": "Tokyo", "country": "Japan", "continent": "Asia", "population": 37.400 }, {"name": "Karachi", "country": "Pakistan", "continent": "Asia", "population": 15.400 }, {"name": "Dhaka", "country": "Bangladesh", "continent": "Asia", "population": 19.578 }, {"name": "Rio de Janeiro", "country": "Brazil", "continent": "South America", "population": 13.293 }, {"name": "São Paulo", "country": "Brazil", "continent": "South America", "population": 21.650 }, {"name": "Mexico City", "country": "Mexico", "continent": "North America", "population": 21.581 }, {"name": "Delhi", "country": "India", "continent": "Asia", "population": 28.514 }, {"name": "Buenos Aires", "country": "Argentina", "continent": "South America", "population": 14.967 }, {"name": "Kolkata", "country": "India", "continent": "Asia", "population": 14.681 }, {"name": "New York", "country": "United States", "continent": "North America", "population": 18.819 }, {"name": "Manila", "country": "Philippines", "continent": "Asia", "population": 13.482 }, {"name": "Chongqing", "country": "China", "continent": "Asia", "population": 14.838 }, {"name": "Istanbul", "country": "Turkey", "continent": "Europe", "population": 14.751 } ])
ユーザーの観点からは、シャーディングされたクラスターは通常の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()
メソッドを使用して、データがシャード全体にどのように分散されたかに関する情報にアクセスできます。
db.cities.getShardDistribution()
このメソッドの出力は、クラスターの一部であるすべてのシャードの統計を提供します。
OutputShard 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
コレクション内のすべてのドキュメントを選択することから始めます。 すべてのドキュメントを取得する必要があるため、クエリを実行するにはすべてのシャードを使用する必要があります。
db.cities.find()
当然のことながら、クエリはすべての都市を返します。 今度はexplain()
メソッドを最後に付けて、クエリを再実行します。
db.cities.find().explain()
長い出力は、クエリがどのように実行されたかについての詳細を提供します。
Output{ "queryPlanner" : { "mongosPlannerVersion" : 1, "winningPlan" : { "stage" : "SHARD_MERGE", "shards" : [ { "shardName" : "shard1", . . . }, { "shardName" : "shard2", . . . } ] } }, . . .
勝利プランはSHARD_MERGE
戦略を参照していることに注意してください。これは、クエリを解決するために複数のシャードが使用されたことを意味します。 shards
キーで、MongoDBは評価に参加しているシャードのリストを返します。 この場合、このリストにはクラスターの両方のシャードが含まれます。
次に、選択したシャードキーではないcontinent
フィールドに対してクエリを実行した場合に、結果が異なるかどうかをテストします。
db.cities.find({"continent": "Europe"}).explain()
今回は、MongoDBもクエリを満たすために両方のシャードを使用する必要がありました。 データベースには、どのシャードにヨーロッパの都市のドキュメントが含まれているかを知る方法がありませんでした。
Output{ "queryPlanner" : { "mongosPlannerVersion" : 1, "winningPlan" : { "stage" : "SHARD_MERGE", . . . } }, . . .
シャードキーに対してフィルタリングする場合、結果は異なるはずです。 以前にシャードキーとして選択したcountry
フィールドを使用して、日本からのみ都市をフィルタリングしてみてください。
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を使用してデータを管理する方法に関するシリーズの他のチュートリアルを確認することをお勧めします。