page_adsence

2014年12月5日金曜日

MongoDBでシャーディングの設定をしてみる

Mongodbでシャーディングを使ってみた。
シャーディングが何たるかはググってもらえればわかると思います。

以前、yum経由でmongoをインストールして起動させていたが、
とりあえずシャーディングの設定するので、そのプロセスは停止させる。

$ sudo service mongod stop

1.各シャード用のディレクトリを作成する。

ここで作成したディレクトリにjournalファイルとか諸々が作成される。
私は下記のディレクトリにディレクトリを作成した。
$ cd /var/lib/mongo/
$ sudo mkdir -p data/config ← configサーバ用のディレクトリ
$ sudo mkdir data/node1      ← シャード1用のディレクトリ
$ sudo mkdir data/node2      ← シャード2用のディレクトリ
$ sudo mkdir log             ← 各サーバのログのディレクトリ
$ sudo chown -R mongod:mongod data log

2.シャードを起動させる

シャードを起動させるコマンドは以下の通り。
ポート番号は使っていないポート番号を指定して、dbpathやlogpathは先ほど作成したディレクトリを指定する。
forkオプションを使用することでバックグラウンドで起動するようになる。

$ sudo -u mongod mongod --shardsvr --port 30000 --dbpath data/node0 --logpath log/node0.log --fork
$ sudo -u mongod mongod --shardsvr --port 30001 --dbpath data/node1 --logpath log/node1.log --fork

※エラーにlogpathを指定しておくと、そこにログファイルが出力されるが、
エラーがあった時にわかりにくいので、最初は--logpath以降は記述しないで試しに起動させてみるほうがいいかもしれない。
こんな感じ。

$ sudo -u mongod --shardsvr --port 30000 --dbpath data/node0

仮想環境とかでディスクの容量が少ないサーバを使っている人はjournalファイルを生成するだけでディスクが一杯になってしまう可能性があるので、
下記のようなsmallfilesオプションをつけてやるとよい。
smallfilesオプションを指定するとjournalファイルが1GB→128MBになる。
mongodbはjournalファイル自体を3ファイル位作成されるので、3GBから384MBに減らすことができるので、大分節約できる。

$ sudo -u mongod mongod --smallfiles --shardsvr --port 30000 --dbpath data/node0 --logpath log/node0.log --fork
$ sudo -u mongod mongod --smallfiles --shardsvr --port 30001 --dbpath data/node1 --logpath log/node1.log --fork

3.コンフィグサーバの起動

$ sudo -u mongod mongod --configsvr --port 20001 --dbpath data/config --logpath log/config.log --fork

4.mongosの起動

sudo -u mongod mongos --configdb localhost:20001 --port 20000 --logpath log/mongos.log --chunkSize 1 --fork

※ここで指定しているチャンクサイズとは分割させる際に、この値に達したら分割というためのしきい値のようなもの。
今回はきちんとチャンクが分割されるかを調べるために、1MBに設定した。

5.プロセスがきちんと立ち上がっているか確認

$ ps aux | grep mongo

6.mongosにログイン

mongosのプロセスを起動させるときに指定したポート番号を指定する。
$ mongo localhost:20000/admin

7.シャードの追加

mongos> sh.addShard("localhost:30000")    // ←30000ポートのmongodを追加
{ "shardAdded" : "shard0000", "ok" : 1 }  // ←okの値が1であれば問題なし

mongos> sh.addShard("localhost:30001")   // ←30001ポートのmongodを追加
{ "shardAdded" : "shard0001", "ok" : 1 }

8.シャードが追加されたか確認

mongos> sh.status()
--- Sharding Status ---
  sharding version: {
        "_id" : 1,
        "version" : 4,
        "minCompatibleVersion" : 4,
        "currentVersion" : 5,
        "clusterId" : ObjectId("547fc2e1390feaa447bb7a48")
}
  shards:
        {  "_id" : "shard0000",  "host" : "localhost:30000" }
        {  "_id" : "shard0001",  "host" : "localhost:30001" }
  databases:
        {  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
        {  "_id" : "freegame_platform_message",  "partitioned" : true,  "primary" : "shard0000" }

9.シャーディングを有効化する

mongos> use admin
switched to db admin
mongos> sh.enableSharding("データベース名")

10.シャードキーを設定する

mongos> sh.shardCollection("freegame_platform_message.message" , { _id : 1, user_id : 1 })
{ "collectionsharded" : "freegame_platform_message.message", "ok" : 1 }

11.シャーディングの状態を確認する

MongoDB shell version: 2.6.5
connecting to: localhost:20000/freegame_platform_message
mongos> sh.status()
--- Sharding Status ---
  sharding version: {
        "_id" : 1,
        "version" : 4,
        "minCompatibleVersion" : 4,
        "currentVersion" : 5,
        "clusterId" : ObjectId("547fc2e1390feaa447bb7a48")
}
  shards:
        {  "_id" : "shard0000",  "host" : "localhost:30000" }
        {  "_id" : "shard0001",  "host" : "localhost:30001" }
  databases:
        {  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
        {  "_id" : "freegame_platform_message",  "partitioned" : true,  "primary" : "shard0000" }
                freegame_platform_message.message
                        shard key: { "_id" : 1, "user_id" : 1 }
                        chunks:
                                shard0000       1
                        { "_id" : { "$minKey" : 1 }, "user_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 }, "user_id" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 0)
        {  "_id" : "logdb",  "partitioned" : false,  "primary" : "shard0001" }

以上でシャーディングの設定は完了。

■補足
コレクションの内容を削除したい場合、dropとremoveがあるが、
MySQL的に言うと、dropはDROP TABLEで、removeはDELETE FROMといった感じ。
truncate的な動きをするメソッドはなさげ。

・コレクションを削除
db.collection.drop()
※コレクションを削除したタイミングでシャードの設定も削除されてしまうので注意。

・コレクション内のデータを削除
db.collection.remove({})
※dropより削除には時間がかかる。

ちなみに、シャードの設定はデータを入れる前でも後でも問題なく振り分けられる。