2012年1月28日土曜日

MongoDB 環境構築(その2: Sharding)。

前回に続き今回は MongoDB の Sharding 環境を構築してみる。
Sharding 環境を構築する事でデータを効果的に分散させて保持し、パフォーマンスの向上を狙う。MongoDB の Sharding では分割用のキーを指定する事でデータが分散して登録される。今回は下記4つの項目を持つログを登録するが、その中で Sharding 用のキーとして {ym, account_id} の2項目を用いる事とする。

登録ドキュメント形式
id ID
uid ユーザID
ymd 年月
timestamp yyyy-mm-dd hh:mm:ss


今回の目標: 3ノードによる Sharding 環境を構築し、データを分散登録する。


上記の構成図にあるようにユーザは Sharding 用のデータ取りまとめノードである mongos のみとデータのやりとりを行い、 mongos が config ノードや mongod01/mongod02 とやり取りする事でユーザにあたかも1台の DB だけとやり取りを行っているように見せる事が可能となる。

サーバを起動
$ mongod --shardsvr --port 10001 --dbpath data/shrd11   // mongod01
$ mongod --shardsvr --port 10002 --dbpath data/shrd12   // mongod02
$ mongod --configsvr --port 10010 --dbpath data/config  // config
$ mongos --configdb localhost:10010 --port 10000        // mongos: config サーバを指定

mongos へ接続し Sharding 環境を設定
$ mongo localhost:10000
MongoDB shell version: 2.0.2
connecting to: localhost:10000/test
mongos>

// Shard を追加
mongos> use admin
mongos> db.runCommand({addshard: 'localhost:10001'});
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> db.runCommand({addshard: 'localhost:10002'});
{ "shardAdded" : "shard0001", "ok" : 1 }

// 登録済 Shard の確認
mongos> db.runCommand({listshards: 1});
{
 "shards" : [
  {
   "_id" : "shard0000",
   "host" : "localhost:10001"
  },
  {
   "_id" : "shard0001",
   "host" : "localhost:10002"
  }
 ],
 "ok" : 1
}

// Sharding 対象 DB を指定
mongos> db.runCommand({enablesharding: 'testdb'});
{ "ok" : 1 }

// Sharding 対象 Collection を指定
mongos> db.runCommand({shardcollection: 'testdb.logs', key: {ymd: 1, uid: 1}});
{ "collectionsharded" : "testdb.logs", "ok" : 1 }

// Sharding の状態を確認
mongos> db.printShardingStatus();
--- Sharding Status --- 
  sharding version: { "_id" : 1, "version" : 3 }
  shards:
 {  "_id" : "shard0000",  "host" : "localhost:10001" }
 {  "_id" : "shard0001",  "host" : "localhost:10002" }
  databases:
 {  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
 {  "_id" : "testdb",  "partitioned" : true,  "primary" : "shard0000" }  // primary shard = localhost:10001
  testdb.logs chunks:
    shard0000 1
   { "ymd" : { $minKey : 1 }, "uid" : { $minKey : 1 } } -->> { "ymd" : { $maxKey : 1 }, "uid" : { $maxKey : 1 } } on : shard0000 { "t" : 1000, "i" : 0 }

お試しデータを登録してみる事にする。
mongos> use testdb
switched to db testdb
mongos> show collections
logs
system.indexes
mongos> db.logs.insert({ymd: 20120128, uid: 12345});

primary shard(localhost:10001) を確認
*デフォルトでは200MBを境に Sharding が実施されるが、それまでは primary shard へデータが登録され続ける
$ mongo localhost:10001
MongoDB shell version: 2.0.2
connecting to: localhost:10001/test

> show dbs
admin (empty)
local (empty)
testdb 0.203125GB
> use testdb
switched to db testdb
> show collections
logs  // ちゃんとある!!
system.indexes

// ちゃんとデータが存在する事を確認
> db.logs.find()
{ "_id" : ObjectId("4f22cf875901ed90a81dbb16"), "ymd" : 20120128, "uid" : 12345 }

// お試しデータなのでちゃんと消しておく
> db.logs.remove()
> db.logs.findOne();
null

次に約300万件のログを mongoimport コマンドで登録してみる。
$ time mongoimport -h localhost:10000 -d testdb -c logs --type csv --headerline --ignoreBlanks --file export_log_data.csv
connected to: localhost:10000
  325564/134551732 0%
   8400 1680/second
  846166/134551732 0%
   21300 2662/second
  1500937/134551732 1%
   37400 3400/second
  2352237/134551732 1%
   58300 4164/second
インポート中…

途中経過を mongos で確認
// shard0000(=localhost:10001)に5つ、shard0001(=localhost:10002)に4つの Chunk(データの分割単位) が存在する事が分かる
mongos> db.printShardingStatus();
--- Sharding Status --- 
  sharding version: { "_id" : 1, "version" : 3 }
  shards:
 {  "_id" : "shard0000",  "host" : "localhost:10001" }
 {  "_id" : "shard0001",  "host" : "localhost:10002" }
  databases:
 {  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
 {  "_id" : "testdb",  "partitioned" : true,  "primary" : "shard0000" }
  testdb.logs chunks:
    shard0000 5  // localhost:10001 の chunk 数
    shard0001 4  // localhost:10002 の chunk 数
   { "ymd" : { $minKey : 1 }, "uid" : { $minKey : 1 } } -->> { "ymd" : NumberLong(20110318), "uid" : 100 } on : shard0000 { "t" : 2000, "i" : 1 }
   { "ymd" : NumberLong(20110318), "uid" : 100 } -->> { "ymd" : NumberLong(20110319), "uid" : 6854 } on : shard0000 { "t" : 1000, "i" : 3 }
   { "ymd" : NumberLong(20110319), "uid" : 6854 } -->> { "ymd" : NumberLong(20110327), "uid" : 35690 } on : shard0001 { "t" : 3000, "i" : 1 }
   { "ymd" : NumberLong(20110327), "uid" : 35690 } -->> { "ymd" : NumberLong(20110403), "uid" : 62791 } on : shard0001 { "t" : 2000, "i" : 5 }
   { "ymd" : NumberLong(20110403), "uid" : 62791 } -->> { "ymd" : NumberLong(20110409), "uid" : 17526 } on : shard0001 { "t" : 3000, "i" : 2 }
   { "ymd" : NumberLong(20110409), "uid" : 17526 } -->> { "ymd" : NumberLong(20110417), "uid" : 78041 } on : shard0001 { "t" : 3000, "i" : 3 }
   { "ymd" : NumberLong(20110417), "uid" : 78041 } -->> { "ymd" : NumberLong(20110425), "uid" : 6578 } on : shard0000 { "t" : 3000, "i" : 6 }
   { "ymd" : NumberLong(20110425), "uid" : 6578 } -->> { "ymd" : NumberLong(20110504), "uid" : 84974 } on : shard0000 { "t" : 3000, "i" : 7 }
   { "ymd" : NumberLong(20110504), "uid" : 84974 } -->> { "ymd" : { $maxKey : 1 }, "uid" : { $maxKey : 1 } } on : shard0000 { "t" : 3000, "i" : 5 }
 {  "_id" : "test",  "partitioned" : false,  "primary" : "shard0001" }

終わったようなのでデータを確認
  133092317/134551732 98%
   3101300 6771/second
  133821849/134551732 99%
   3118000 6763/second
  134390051/134551732 99%
   3131000 6747/second
imported 3134701 objects  // ヘッダ行を含むのでデータは 3134700 レコード

mongos> db.printShardingStatus();
--- Sharding Status --- 
  sharding version: { "_id" : 1, "version" : 3 }
  shards:
 {  "_id" : "shard0000",  "host" : "localhost:10001" }
 {  "_id" : "shard0001",  "host" : "localhost:10002" }
  databases:
 {  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
 {  "_id" : "testdb",  "partitioned" : true,  "primary" : "shard0000" }
  testdb.logs chunks:
    shard0000 7
    shard0001 11
   { "ymd" : { $minKey : 1 }, "uid" : { $minKey : 1 } } -->> { "ymd" : NumberLong(20110318), "uid" : 100 } on : shard0000 { "t" : 4000, "i" : 1 }
   { "ymd" : NumberLong(20110318), "uid" : 100 } -->> { "ymd" : NumberLong(20110319), "uid" : 6854 } on : shard0000 { "t" : 1000, "i" : 3 }
   { "ymd" : NumberLong(20110319), "uid" : 6854 } -->> { "ymd" : NumberLong(20110327), "uid" : 35690 } on : shard0001 { "t" : 5000, "i" : 1 }
   { "ymd" : NumberLong(20110327), "uid" : 35690 } -->> { "ymd" : NumberLong(20110403), "uid" : 62791 } on : shard0001 { "t" : 2000, "i" : 5 }
   { "ymd" : NumberLong(20110403), "uid" : 62791 } -->> { "ymd" : NumberLong(20110409), "uid" : 17526 } on : shard0001 { "t" : 3000, "i" : 2 }
   { "ymd" : NumberLong(20110409), "uid" : 17526 } -->> { "ymd" : NumberLong(20110417), "uid" : 78041 } on : shard0001 { "t" : 3000, "i" : 3 }
   { "ymd" : NumberLong(20110417), "uid" : 78041 } -->> { "ymd" : NumberLong(20110425), "uid" : 6578 } on : shard0000 { "t" : 3000, "i" : 6 }
   { "ymd" : NumberLong(20110425), "uid" : 6578 } -->> { "ymd" : NumberLong(20110504), "uid" : 84974 } on : shard0000 { "t" : 3000, "i" : 7 }
   { "ymd" : NumberLong(20110504), "uid" : 84974 } -->> { "ymd" : NumberLong(20110519), "uid" : 103548 } on : shard0000 { "t" : 3000, "i" : 8 }
   { "ymd" : NumberLong(20110519), "uid" : 103548 } -->> { "ymd" : NumberLong(20110614), "uid" : 134231 } on : shard0000 { "t" : 3000, "i" : 10 }
   { "ymd" : NumberLong(20110614), "uid" : 134231 } -->> { "ymd" : NumberLong(20110718), "uid" : 141818 } on : shard0001 { "t" : 4000, "i" : 2 }
   { "ymd" : NumberLong(20110718), "uid" : 141818 } -->> { "ymd" : NumberLong(20110806), "uid" : 16293 } on : shard0001 { "t" : 4000, "i" : 6 }
   { "ymd" : NumberLong(20110806), "uid" : 16293 } -->> { "ymd" : NumberLong(20110905), "uid" : 153701 } on : shard0001 { "t" : 4000, "i" : 7 }
   { "ymd" : NumberLong(20110905), "uid" : 153701 } -->> { "ymd" : NumberLong(20110930), "uid" : 141517 } on : shard0001 { "t" : 4000, "i" : 10 }
   { "ymd" : NumberLong(20110930), "uid" : 141517 } -->> { "ymd" : NumberLong(20111104), "uid" : 165311 } on : shard0001 { "t" : 4000, "i" : 11 }
   { "ymd" : NumberLong(20111104), "uid" : 165311 } -->> { "ymd" : NumberLong(20111206), "uid" : 132993 } on : shard0001 { "t" : 5000, "i" : 2 }
   { "ymd" : NumberLong(20111206), "uid" : 132993 } -->> { "ymd" : NumberLong(20120117), "uid" : 183726 } on : shard0001 { "t" : 5000, "i" : 3 }
   { "ymd" : NumberLong(20120117), "uid" : 183726 } -->> { "ymd" : { $maxKey : 1 }, "uid" : { $maxKey : 1 } } on : shard0000 { "t" : 5000, "i" : 0 }
 {  "_id" : "test",  "partitioned" : false,  "primary" : "shard0001" }

mongos> use testdb
switched to db testdb
mongos> db.logs.count()
3134700
mongos> db.logs.findOne()
{
 "_id" : ObjectId("4f22d4428b618b0098535103"),
 "uid" : 100,
 "ymd" : NumberLong(20110318),
 "id" : 1,
 "timestamp" : "2011-03-18 22:02:13"
}

localhost:10001 を確認
$ mongo localhost:10001
MongoDB shell version: 2.0.2
connecting to: localhost:10001/test

> use testdb
switched to db testdb
> db.logs.count()
935965
> db.logs.findOne()
{
 "_id" : ObjectId("4f22d4428b618b0098535103"),
 "uid" : 100,
 "ymd" : NumberLong(20110318),
 "id" : 1,
 "timestamp" : "2011-03-18 22:02:13"
}
localhost:10002 を確認
$ mongo localhost:10002
MongoDB shell version: 2.0.2
connecting to: localhost:10002/test

> use testdb
switched to db testdb
> db.logs.count()
2198735
> db.logs.findOne()
{
 "_id" : ObjectId("4f22d4438b618b0098536b6b"),
 "uid" : 6854,
 "ymd" : NumberLong(20110319),
 "id" : 6760,
 "timestamp" : "2011-03-19 19:09:41"
}
935965 + 2198735 = 3134700 でドキュメント数の整合性がちゃんと取れている事が分かる。

最後に mongod01 を停止した上でのデータアクセスについて検証してみる。

mongos からのデータアクセスを検証
// mongod01 を停止
^C

// mongos に接続
$ mongo localhost:10000
MongoDB shell version: 2.0.2
connecting to: localhost:10000/test

// エラー発生
mongos> show dbs
Sat Jan 28 02:12:16 uncaught exception: error { "$err" : "socket exception", "code" : 11002 }
mongos> use testdb
switched to db testdb
mongos> show collections
Sat Jan 28 02:12:28 uncaught exception: error: { "$err" : "socket exception", "code" : 11002 }
mongos> db.logs.count()
Sat Jan 28 02:12:43 uncaught exception: error { "$err" : "socket exception", "code" : 11002 }
mongos> db.logs.find()
error: {
 "$err" : "could not initialize cursor across all shards because : socket exception @ localhost:10001",
 "code" : 14827
}

mongod02 からのデータアクセスを検証
// mongod02 に接続
$ mongo localhost:10002
MongoDB shell version: 2.0.2
connecting to: localhost:10002/test

// こちらはデータアクセス可能
> show dbs
admin (empty)
local (empty)
testdb 1.953125GB
> use testdb
switched to db testdb
> show collections
logs
system.indexes
> db.logs.count()
2198735
> db.logs.findOne()
{
 "_id" : ObjectId("4f22d4438b618b0098536b6b"),
 "uid" : 6854,
 "ymd" : NumberLong(20110319),
 "id" : 6760,
 "timestamp" : "2011-03-19 19:09:41"
}

今回は Sharding 環境の構築を行った。
次回は ReplicaSet+Sharding で『可用性の確保+データの分散保持』を行ってみる。

0 件のコメント:

コメントを投稿