読者です 読者をやめる 読者になる 読者になる

日頃の行い

個人的な日頃の行いをつらつら書いてます\\\\ ٩( 'ω' )و ////

MongoDBでシャーディングを試してみるの巻

MongoDB

みなさんこんにちは、@ara_ta3です。
この記事はMongoDB Advent Calendar 2014 - Qiita
の13日目として書かれてます。


private DMPの開発にMongoDBを利用していて、すごく大変なこともありますが、
最近がんばりやさんなMongoDBが愛おしくなってきたので
MongoDBについてもっと知ろうと思います。


今回はShardingのチュートリアルを読んで、
実際にやってみようと思います。
Sharded Cluster Tutorials — MongoDB Manual 3.0.2

(あれ・・・結構長くね・・・
と絶望しかけましたが、主に2種類ですかね。

シャードクラスタを作るチュートリアル
Sharded Cluster Deployment Tutorials — MongoDB Manual 3.0.2

シャードクラスタのメンテナンスチュートリアル
Sharded Cluster Tutorials — MongoDB Manual 3.0.2

とりあえず、前者をやってみようと思います。
(あれ・・・・・やっぱ・・・長くね・・・←
ごめんなさい。
ほんとにシャーディングを試しただけです。
ほんとはシャーディングして、パフォーマンスとかも試したかったんです・・・orz

シャーディングで行うこと

  1. Configサーバの準備
  2. mongosのセットアップ
  3. mongosからシャードを追加

です。
Configサーバがどのシャードにどのデータがあるかに関するメタデータを保持し、データ自体はそれぞれのシャードサーバに置く感じですね。

Configサーバの準備

6台(Config, Mongoそれぞれ3台)作ってみる予定でしたが、1台でやりました。
実際にProduction環境でやる場合でも、IPアドレスやポートが異なるのみなので、特に設定方法に影響はなさそうですね。
ただ、パフォーマンスの検証はネットワーク等も考慮したいので、何台かに分けるべきでしょう。

Configサーバの設定

https://github.com/tarata/mongo-sharding-getting-started/blob/master/script/mongod-install/cnfserver.sh

for i in 1 2 3; do
    mkdir -p /data/configdb${i}
    nohup mongod --configsvr --dbpath /data/configdb${i} --port `expr 27018 + ${i}` &
done

Configサーバにするためには mongod起動時に `--configsvr` というオプションをつければ良いようです。

mongosのセットアップ

mongosの起動時にConfigサーバがどこにあるかを伝える形ですね。

nohup mongos --configdb 127.0.0.1:27019,127.0.0.1:27020,127.0.0.1:27021 &

mongosからシャードを追加

  1. シャードに追加
  2. シャーディング設定を有効
  3. コレクションをシャーディング設定に乗せる

というような流れです。

今回は下記を参考にしたダミーデータを突っ込むため、xというプロパティをキーにシャーディングします。

Getting Started with MongoDB (MongoDB Shell Edition) — Getting Started With MongoDB 3.0.1


※コレクションにデータが先に入っている場合、Indexを貼る必要があり、 sh.shardCollection 時にエラーが出ます。
 データが空の場合、勝手にIndexを貼ってくれるそうです。


# mongodを起動します(実際にデータを置くサーバ)

for i in 1 2 3; do
    mkdir -p /data/mongod${i}
    port=`expr 28016 + ${i}`
    nohup mongod --dbpath /data/mongod${i} --port $port & # mongodの起動
    mongo --eval "sh.addShard( 'localhost:$port' )" # シャードに追加
done

mongo --eval 'sh.enableSharding("test")' #シャーディング設定を有効
mongo --eval 'sh.shardCollection("test.testData", { "x": 1} )' # コレクションをシャーディング設定に乗せる

# 先にデータが入ってる場合、"errmsg" : "please create an index that starts with the shard key before sharding." というエラーがでます。
# この時はインデックスを貼る必要があります。
# e.g.) db.testData.ensureIndex({x : 1}) 

これでシャーディングの設定は終了です。
この状態でダミーデータを突っ込んでみましょう。

mongos > for (var i = 1; i <= 10000; i++) {
   db.testData.insert( { x : i } )
}

さぁシャーディングの設定は?(・∀・)

mongos> db.printShardingStatus()
--- Sharding Status ---
  sharding version: {
	"_id" : 1,
	"version" : 4,
	"minCompatibleVersion" : 4,
	"currentVersion" : 5,
	"clusterId" : ObjectId("548bfb6cc042b17f52e0a43e")
}
  shards:
	{  "_id" : "shard0000",  "host" : "localhost:28017" }
	{  "_id" : "shard0001",  "host" : "localhost:28018" }
	{  "_id" : "shard0002",  "host" : "localhost:28019" }
  databases:
	{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
	{  "_id" : "test",  "partitioned" : true,  "primary" : "shard0000" }
		test.testData
			shard key: { "x" : 1 }
			chunks:
				shard0001	1
				shard0000	1
				shard0002	1
			{ "x" : { "$minKey" : 1 } } -->> { "x" : 1 } on : shard0001 Timestamp(2, 0)
			{ "x" : 1 } -->> { "x" : 12059 } on : shard0000 Timestamp(3, 1)
			{ "x" : 12059 } -->> { "x" : { "$maxKey" : 1 } } on : shard0002 Timestamp(3, 0)

なんか動いていそうですね。
データはどうなってるのでしょう。

mongos> db.testData.count()
100000
# mongosで実行するとデータを入れた100000件

[vagrant@localhost ~]$ mongo --port=28017
MongoDB shell version: 2.6.6
connecting to: 127.0.0.1:28017/test
> db.testData.count()
12058
# 3台中1台目は 12058件

[vagrant@localhost ~]$ mongo --port=28018
MongoDB shell version: 2.6.6
connecting to: 127.0.0.1:28018/test
> db.testData.count()
0
# 3台中2台目は 0件(あれ・・・w


[vagrant@localhost ~]$ mongo --port=28019
MongoDB shell version: 2.6.6
connecting to: 127.0.0.1:28019/test
> db.testData.count()
87942
# 3台中3台目は87942件(よかった・・・w

ちゃんと分かれているようですね。
これがミニマムのシャーディングになるかと思います。
次は、シャーディングに利用するキーに関することや、
シャーディングによるパフォーマンスの影響など見て行きたいなと思います。

今回利用したレポジトリはこちらです。tarata/mongo-sharding-getting-started · GitHub

明日の担当の方は・・・いなかったですね・・・
これは明日もやるぱたーん?