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

ReplicaSetとかShardingとかためしてみる(Sharding編)

MongoDB

ReplicaSetを前回のエントリで構築できたので早速Shardingの設定にいってみます。
Shardingについては以下。


とりあえずconfigサーバなるメタデータ格納用のサーバを立ち上げます。
必須パラメータは「--configsvr」です。
デフォルトでは27019ポートにバインドするみたい。

mongod --configsvr --dbpath /data/mongodb/conf --logpath /var/log/mongodb/conf.log --logappend --pidfilepath /data/mongodb/conf.pid --directoryperdb --fork --rest


続けて各shardへのルーティングを行うmongosを立ち上げます。
デフォルトでは27017ポートにバインドしますが27017はちょっと別のmongo用に使ってたので他のポートを指定してます。
chunkの確認もしたかったので「--chunkSize」も指定しときます。
これを指定しないとデフォルトのサイズ(1.8では64M、1.6では200M)が使われて確認がめんどくさそうなので。

mongos --configdb localhost:27019 --port 27020 --logpath /var/log/mongodb/mongos.log --logappend --pidfilepath /data/mongodb/mongos.pid --fork --chunkSize 1


正常に立ち上がったようなので早速mongosに入ってShardingの設定をしてみます。

mongo --port 27020 admin
> db.runCommand({addshard:"set01/***.***.***.***:10001,***.***.***.***:10002,***.***.***.***:10003",name:"set01"});
{
        "ok" : 0,
        "errmsg" : "can't use localhost as a shard since all shards need to communicate. either use all shards and configdbs in localhost or all in actual IPs "
}


なんかエラーでた。
configサーバとshardは全てlocalhostか全て実IP指定かどっちかにしろってことでしょうか。

とりあえずconfigサーバに実IP指定してみます。
ついでなのでshardのIPのところはhost名に書き換えてみます。

mongos --configdb ***.***.***.***:27019 --port 27020 --logpath /var/log/mongodb/mongos.log --logappend --pidfilepath /data/mongodb/mongos.pid --fork

> db.runCommand({addshard:"set01/mongodb01:10001,mongodb01:10002,mongodb01:10003",name:"set01"});               
{
        "ok" : 0,
        "errmsg" : "host mongodb01:10001 does not belong to replica set as a non-passive memberset01"
}


またおこられた。ReplicaSetの設定も変更してみる。
とりあえずset01のprimaryに入って下記を参考にReplicaSetを再構築します。
Deploy a Replica Set — MongoDB Manual 2.4.8

set01:PRIMARY> new_config = {_id:'set01',members:[{_id:0, host:'mongodb01:10001'},{_id:1, host:'mongodb01:10002'},{_id:2, host:'mongodb01:10003'}]}
set01:PRIMARY> use local
set01:PRIMARY> old_config=db.system.replset.findOne();
set01:PRIMARY> new_config.version=old_config.version+1; 
set01:PRIMARY> use admin
set01:PRIMARY> db.runCommand({replSetReconfig:new_config});
set01:PRIMARY> rs.status()
{
        "set" : "set01",
        "date" : ISODate("2011-05-11T13:28:40Z"),
        "myState" : 1,
        "members" : [
                {
                        "_id" : 0,
                        "name" : "***.***.***.***:10001",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "optime" : {
                                "t" : 1305116528000,
                                "i" : 7281
                        },
                        "optimeDate" : ISODate("2011-05-11T12:22:08Z"),
                        "self" : true
                },
                {
                        "_id" : 1,
                        "name" : "mongodb01:10002",
(略)
                }
        ],
        "ok" : 1
}


反映されてない…!
nameがmongodb01になってて欲しかったんですけど。
困ったときの再起動ということでReplicaSet全部落として再度試します。

set01:PRIMARY> rs.status()
{
        "set" : "set01",
        "date" : ISODate("2011-05-11T13:28:40Z"),
        "myState" : 1,
        "members" : [
                {
                        "_id" : 0,
                        "name" : "mongodb01:10001",
                        "health" : 1,
                        "state" : 1,
                        "stateStr" : "PRIMARY",
                        "optime" : {
                                "t" : 1305116528000,
                                "i" : 7281
                        },
                        "optimeDate" : ISODate("2011-05-11T12:22:08Z"),
                        "self" : true
                },
                {
                        "_id" : 1,
                        "name" : "mongodb01:10002",
(略)
                }
        ],
        "ok" : 1
}


いけた。
こういうものなのかな。
あんまりやらないオペレーションだとは思うけどmember増やすときとかちょっと不安。


hostsの設定をmongosの乗ってるサーバでもして改めてShardingの設定を試してみます。

> db.runCommand({addshard:"set01/mongodb01:10001,mongodb01:10002,mongodb01:10003",name:"set01"});
{ "shardAdded" : "set01", "ok" : 1 }


いけた…!
同じようにset02、03も設定します。
完了したらconfigサーバに入って確認!

> db.shards.find()
{ "_id" : "set01", "host" : "set01/mongodb01:10001,mongodb01:10002,mongodb01:10003" }
{ "_id" : "set02", "host" : "set02/mongodb02:10001,mongodb02:10002,mongodb02:10003" }
{ "_id" : "set03", "host" : "set03/mongodb03:10001,mongodb03:10002,mongodb03:10003" }


どうやらいけてる模様。
準備は整ったので実際にDBとコレクションをShardingの対象にしてみます。

> db.runCommand({enablesharding:"test"})
{ "ok" : 1 }

> db.printShardingStatus()
--- Sharding Status --- 
  sharding version: { "_id" : 1, "version" : 3 }
  shards:
      {
        "_id" : "set01",
        "host" : "set01/mongodb01:10001,mongodb01:10003,mongodb01:10002"
}
      {
        "_id" : "set02",
        "host" : "set02/mongodb02:10001,mongodb02:10003,mongodb02:10002"
}
      {
        "_id" : "set03",
        "host" : "set03/mongodb03:10001,mongodb03:10003,mongodb03:10002"
}
  databases:
        { "_id" : "admin", "partitioned" : false, "primary" : "config" }
        { "_id" : "test2", "partitioned" : true, "primary" : "set02" }


set02をprimaryとして「test」DBのShardingが有効になったみたい。
set02でも確認してみます。

set01:PRIMARY> show dbs
admin   (empty)
local   1.203125GB
test2    (empty)

あるある。でもset01と03にはまだデータがないのでtest2自体存在しません。
次にコレクションをSharding対象にします。
自動でindex作られるみたいなことをどっかで見ましたが、先駆けてindexを作成しときます。
indexは一旦適当です。

> db.table01.ensureIndex({createdDatetime:1,entryId:1});
> db.table01.getIndexes()
[
        {
                "name" : "_id_",
                "ns" : "test2.table01",
                "key" : {
                        "_id" : 1
                },
                "v" : 0
        },
        {
                "_id" : ObjectId("4dca5d3b4c06e48a77e298cb"),
                "ns" : "test2.table01",
                "key" : {
                        "createdDatetime" : 1,
                        "entryId" : 1
                },
                "name" : "createdDatetime_1_entryId_1",
                "v" : 0
        }
]


続けてcollectionにindexと同じものをShardKeyに指定してshardCollectionを実行します。

> use admin
switched to db admin
> db.runCommand({shardCollection:"test2.table01",key:{createdDatetime:1,entryId:1}});           
{ "collectionsharded" : "test2.table01", "ok" : 1 }
> db.printShardingStatus()
--- Sharding Status --- 
  sharding version: { "_id" : 1, "version" : 3 }
  shards:
      {
        "_id" : "set01",
        "host" : "set01/mongodb01:10001,mongodb01:10003,mongodb01:10002"
}
      {
        "_id" : "set02",
        "host" : "set02/mongodb02:10001,mongodb02:10003,mongodb02:10002"
}
      {
        "_id" : "set03",
        "host" : "set03/mongodb03:10001,mongodb03:10003,mongodb03:10002"
}
  databases:
        { "_id" : "admin", "partitioned" : false, "primary" : "config" }
        { "_id" : "test", "partitioned" : true, "primary" : "set01" }
                test2.table01 chunks:
                                set02   1
                        { "createdDatetime" : { $minKey : 1 }, "entryId" : { $minKey : 1 } } -->> { "createdDatetime" : { $maxKey : 1 }, "entryId" : { $maxKey : 1 } } on : set02 { "t" : 1000, "i" : 0 }
        { "_id" : "test2", "partitioned" : true, "primary" : "set02" }
                test2.table01 chunks:
                                set02   1
                        { "createdDatetime" : { $minKey : 1 }, "entryId" : { $minKey : 1 } } -->> { "createdDatetime" : { $maxKey : 1 }, "entryId" : { $maxKey : 1 } } on : set02 { "t" : 1000, "i" : 0 }


何故か別のテスト用に作ったtestの方にも反映されている…。
一旦考えないことにして先に進めます…。


データの分割を確認するべくデータをたくさんぶちこんでみます。

> for(var i=1;i<=5000;i++) db.table01.save({entryId:i,createdDatetime:new Date(),text:"test0"+i});

db.printShardingStatus()するも変化なし。んんん?
データが少ないのかもしれないのでついカッとなって15万件までぶちこんだら変化がありました。

> db.printShardingStatus()
(略)
        { "_id" : "test2", "partitioned" : true, "primary" : "set02" }
                test2.table01 chunks:
                                set03   1
                                set02   2
                                set01   1
                        { "createdDatetime" : { $minKey : 1 }, "entryId" : { $minKey : 1 } } -->> { "createdDatetime" : ISODate("2011-05-11T09:51:25.418Z"), "entryId" : 1 } on : set03 { "t" : 2000, "i" : 0 }
                        { "createdDatetime" : ISODate("2011-05-11T09:51:25.418Z"), "entryId" : 1 } -->> {
        "createdDatetime" : ISODate("2011-05-11T11:38:21.927Z"),
        "entryId" : 67510
} on : set02 { "t" : 3000, "i" : 1 }
                        {
        "createdDatetime" : ISODate("2011-05-11T11:38:21.927Z"),
        "entryId" : 67510
} -->> {
        "createdDatetime" : ISODate("2011-05-11T11:38:33.941Z"),
        "entryId" : 128707
} on : set02 { "t" : 2000, "i" : 4 }
                        {
        "createdDatetime" : ISODate("2011-05-11T11:38:33.941Z"),
        "entryId" : 128707
} -->> { "createdDatetime" : { $maxKey : 1 }, "entryId" : { $maxKey : 1 } } on : set01 { "t" : 3000, "i" : 0 }


どうやら分割されたみたい。
configサーバでも確認してみる。

> db.chunks.find()  
{ "_id" : "test2.table01-createdDatetime_MinKeyentryId_MinKey", "lastmod" : { "t" : 2000, "i" : 0 }, "ns" : "test2.table01", "min" : { "createdDatetime" : { $minKey : 1 }, "entryId" : { $minKey : 1 } }, "max" : { "createdDatetime" : ISODate("2011-05-11T09:51:25.418Z"), "entryId" : 1 }, "shard" : "set03" }
{ "_id" : "test2.table01-createdDatetime_new Date(1305107485418)entryId_1.0", "lastmod" : { "t" : 3000, "i" : 1 }, "ns" : "test2.table01", "min" : { "createdDatetime" : ISODate("2011-05-11T09:51:25.418Z"), "entryId" : 1 }, "max" : { "createdDatetime" : ISODate("2011-05-11T11:38:21.927Z"), "entryId" : 67510 }, "shard" : "set02" }
{ "_id" : "test2.table01-createdDatetime_new Date(1305113901927)entryId_67510.0", "lastmod" : { "t" : 2000, "i" : 4 }, "ns" : "test2.table01", "min" : { "createdDatetime" : ISODate("2011-05-11T11:38:21.927Z"), "entryId" : 67510 }, "max" : { "createdDatetime" : ISODate("2011-05-11T11:38:33.941Z"), "entryId" : 128707 }, "shard" : "set02" }
{ "_id" : "test2.table01-createdDatetime_new Date(1305113913941)entryId_128707.0", "lastmod" : { "t" : 3000, "i" : 0 }, "ns" : "test2.table01", "min" : { "createdDatetime" : ISODate("2011-05-11T11:38:33.941Z"), "entryId" : 128707 }, "max" : { "createdDatetime" : { $maxKey : 1 }, "entryId" : { $maxKey : 1 } }, "shard" : "set01" }


entryIdの値が67510と128707を境に分割されてるみたい。
set03はどうなってるのかよく分からない。
試しにそれぞれのsetに入ってどんだけデータが入ってるか見てみます。

set01:PRIMARY> db.table01.find().count()
21294

set02:PRIMARY> db.table01.find().count()
128706

set03:PRIMARY> db.table01.find().count()
0


うむ。
とりあえず分割は確認できました。とりあえず。すごい偏ってるけど。
他にもshardCollectionのとき何で関係ないはずのDBに反映されたのかなとかchunkSize効いてなくね?とか色々不明点はあるので綺麗にしてもっかい試してみようとおもいます。

スポンサーリンク