MongoDBのShardingを試してみる
こんにちは。RGA(リアルグローブ・オートメーティッド)でインフラエンジニアをしている張です。
前回の記事では、MongoDBのReplicationをローカルで組んでみたのですが、今回はその続きでShardingを試してみたいと思います。
まずは、MongoDBのReplicationとShardingの違いを簡単に見ておきましょう。まず、Replicationは、3つのフォルダに1つのDBを同様に配置すると理解してもらってもいいと思います。つまり、このようなイメージになります。
これに対してShardingは、レプリカセットをさらにカットしてDBを分割し、別のマシンに配置すると考えることができます。つまり、下のようなイメージです。
構築イメージ
今回はShardが2つある構成を構築してみたいと思います。
アーキテクチャ図
下記のように3つのVM(yuantst01, yuantst02, yuantst03)にShard、Config サーバ、Router(mongos)を配置するイメージです。
環境
環境は以下の通りです。
VM: ubuntu 20.04(LTS) 3台、メモリ4GB/ディスク20GB
yuantst01 (139.59.190.209)
yuantst02 (139.59.182.250)
yuantst03 (139.59.178.240)
MongoDB: 5.0.2 (各VMにインストール)
ドメイン指定
前回はポート番号を分けることで1台のVM上でReplicationを作成しましたが、今回のShardingの作成ではポート番号は分けません。その代わりにDBを3つのVMに配置するこで、Shardを分割します。アーキテクチャ図を表で書くと、下記のようになります。
なお、レプリカセットには、メンバー(1つのPrimary, 2つのSecondary)があります。そのコンセプトを使って、下図のmember1,member3,member5をshard1(レプリカセットのようなもの)の3つメンバーとして作成しています(member2,member4,member6をshard2の3つメンバーとして作成すると理解していただいてもよいです)。
セットアップ手順
以下の手順でセットアップを行います。
ドメイン設定(hosts追加)
Shardingディレクトリを用意
1つ目のShardを作成して初期化
Config サーバのレプリカセットを作成して初期化
Router(mongos)を設定
大量データを作成(Shardキーをhashedで設定)
2つ目のShardを追加
Router(mongos)に配置
それぞれについて見ていきましょう。
1. 各VMにhosts設定を追加
まずはhostsの設定です。3つのVMそれぞれに対して行います。
echo "139.59.190.209 yuantst01 member1.example.com member2.example.com" >> /etc/hosts
echo "139.59.182.250 yuantst02 member3.example.com member4.example.com" >> /etc/hosts
echo "139.59.178.240 yuantst03 member5.example.com member6.example.com" >> /etc/hosts
2. ディレクトリを用意
次に各VMにディレクトリを作成します。
mkdir -p /data/shard1/
mkdir -p /data/config/
mkdir -p /data/shard2/
mkdir -p /data/mongos/
3. 1つ目のシャードを設定
mongod --bind_ip 0.0.0.0 --replSet shard1 --dbpath /data/shard1 --logpath /data/shard1/mongod.log --port 27010 --fork --shardsvr --wiredTigerCacheSizeGB 1
引数の "--shardsvr --wiredTigerCacheSizeGB 1" は内部キャッシュの最大値を少なめに(1GB)設定する指定です。 なお、メモリ4GBのVMに対しては、デフォルトのキャッシュ値は1.5GBになります。
参考: storage.wiredTiger.engineConfig.cacheSizeGB
mongo member1.example.com:27010 --quiet
rs.initiate({ _id: "shard1", members: [{ _id: 0, host: "member1.example.com:27010"},{_id: 1, host: "member3.example.com:27010"},{_id: 2,host:"member5.example.com:27010"}]})
4. configサーバを設定
次にconfigサーバの設定を行います。
mongod --bind_ip 0.0.0.0 --replSet config --dbpath /data/config --logpath /data/config/mongod.log --port 27019 --fork --configsvr --wiredTigerCacheSizeGB 1
mongo member1.example.com:27019 --quiet
rs.initiate({ _id: "config", members: [{ _id: 0, host: "member1.example.com:27019"},{_id: 1, host: "member3.example.com:27019"},{_id: 2,host:"member5.example.com:27019"}]})
5. mongosを設定
mongosの設定です。
mongos --bind_ip 0.0.0.0 --logpath /data/mongos/mongos.log --port 27017 --fork --configdb config/member1.example.com:27019,member3.example.com:27019,member5.example.com:27019
mongo member1.example.com:27017 --quiet
sh.addShard("shard1/member1.example.com:27010,member3.example.com:27010,member5.example.com:27010");
追加が終わったら、詳細を確認します。
sh.status()
6. 大量なデータを作成
シャード(foo)用のCollection(bar)をデフォルトフィールドの_idをhashedというShard Keysとして作成します。
sh.enableSharding("foo");
sh.shardCollection("foo.bar",{_id: 'hashed'});
確認のため、10000件のデータを作成します。
use foo
for (var i=0; i<10000; i++) {
db.bar.insert({i: i});
}
作成したCollectionの状況を確認します。
上図から、chunks: shard1 2...と返されていることがわかります。これは、barというコレクションが、2つのChunkで分割されていることを示しています。
どのように分割されているのかは、{"_id" : {"$minKey" : 1 }} -->> {"_id" : NumberLong(0) } on : shard1 Timestamp(1, 0)...と2つの形に分かれていることがわかります。
データの範囲を使ってShard キー指定する方法もありますが、hashed という形で試したかったので、デフォルトの_idフィールドで指定してます。目でデータを確認するとき、分かりづらいと思われがちですが、これが推奨されている方法です。
出典: Hashed Sharding Shard Key
直訳すると、
となります。
7. 2つ目のシャードを設定
1つ目のシャードを作成する方法と同様に、2つ目のシャードを設定します。
mongod --bind_ip 0.0.0.0 --replSet shard2 --dbpath /data/shard2 --logpath /data/shard2/mongod.log --port 27011 --fork --shardsvr --wiredTigerCacheSizeGB 1
mongo member2.example.com:27011 --quiet
rs.initiate({ _id: "shard2", members: [{ _id: 0, host: "member2.example.com:27011"},{_id: 1, host: "member4.example.com:27011"},{_id: 2,host:"member6.example.com:27011"}]})
8. 2つ目のシャードをmongosに追加
mongo member1.example.com:27017 --quiet
sh.addShard("shard2/member2.example.com:27011,member4.example.com:27011,member6.example.com:27011");
sh.status()
シャードfooのCollection(bar)を確認します。
sh.status()
別のVMでもシャーディングの状況も確認できます。yuantst02では、下のように表示されました。
実際、Collection(bar)のデータはどのように分割されているのかをGUI(Compass)で確認してみましょう。
Shard1は、10000件データのうち、4996件がこちらに格納されています。
Shard2は、10000件データのうち、5004件がこちらに格納されています。
無事にShardingで分割できていることが確認できました。
――――――――――――――――――――――――――――――――――
【ご案内】
ITシステム開発やITインフラ運用の効率化、高速化、品質向上、その他、情シス部門の働き方改革など、IT自動化導入がもたらすメリットは様々ございます。
IT業務の自動化にご興味・ご関心ございましたら、まずは一度、IT自動化の専門家リアルグローブ・オートメーティッド(RGA)にご相談ください!
お問合せは以下の窓口までお願いいたします。
【お問い合わせ窓口】
代表窓口:info@rg-automated.jp
URL: https://rg-automated.jp