2012年5月12日土曜日

MongoDBのマイグレーション(Migration)中のcountの挙動について検証したときのメモ

# ----------------------------------
概要
# ----------------------------------
MongoDBのマイグレーション中に起きるcount()の問題を検証した。
↓↓問題については@doryokujinさんのslide share資料
Mongo sharding
↓↓こちらの記事も検証、図がわかりやすかったです。
MongoDBのShardingを試してみた。その2 Migration中の挙動について


シャードキーで検索、全件検索、snapshot()での検索、index()での検索、いずれの場合でもcount()結果がずれる。


# ----------------------------------
# mongo dbのバージョンは2系
# ----------------------------------
mongod --version
db version v2.0.4, pdfile version 4.5
Fri May 11 21:59:13 git version: 329f3c47fe8136c03392c8f0e548506cb21f8ebf

# ----------------------------------
# 構成
# ----------------------------------
macbook-air-13inch: {
  mongos : [27017],
  config : [11100],
  sharding: {
    replica_set1 : {
      shards: [10011, 10012],
    },
    replica_set2 : {
      shards: [10021, 10022],
    },
  }
}
# arbiterは省略

# 1,000万件のデータ投入
use ryooo
ins_humongous = function(){
  n = Math.random() * 100000000
  db.test_humongous.insert({number: parseInt(n)})
}
for (i = 0; i <= 10000000; i++) {
  ins_humongous()
}


# 最初は798969件だった
mongos> use ryooo
switched to db ryooo
mongos> db.test_humongous.find({ number : {$gt: 100,  $lt: 8000000}}).count();
798969

# numberにindexはついていない
mongos> db.test_humongous.stats()
{
 ・
 ・
 "totalIndexSize" : 324603552,
 "indexSizes" : {
  "_id_" : 324603552
 },
}


# ----------------------------------
# migration開始
# ----------------------------------
mongos> use admin
switched to db admin
mongos> db.runCommand({shardcollection : "ryooo.test_humongous", key: {_id : 1}});
{ "collectionsharded" : "ryooo.test_humongous", "ok" : 1 }


# migration中
mongos> use ryooo
switched to db ryooo
mongos> db.test_humongous.getShardDistribution()

Shard Shard1 at Shard1/localhost:10011,localhost:10012
 data : 311.77Mb docs : 8172914 chunks : 13
 estimated data per chunk : 23.98Mb
 estimated docs per chunk : 628685

Shard Shard2 at Shard2/localhost:10021,localhost:10022
 data : 75Mb docs : 1966082 chunks : 3
 estimated data per chunk : 25Mb
 estimated docs per chunk : 655360

Totals
 data : 386.77Mb docs : 10138996 chunks : 16
 Shard Shard1 contains 80.6% data, 80.6% docs in cluster, avg obj size on shard : 40b
 Shard Shard2 contains 19.39% data, 19.39% docs in cluster, avg obj size on shard : 40b


# migration後
mongos> db.test_humongous.getShardDistribution()

Shard Shard1 at Shard1/localhost:10011,localhost:10012
 data : 181.47Mb docs : 4757215 chunks : 8
 estimated data per chunk : 22.68Mb
 estimated docs per chunk : 594651

Shard Shard2 at Shard2/localhost:10021,localhost:10022
 data : 200Mb docs : 5242887 chunks : 8
 estimated data per chunk : 25Mb
 estimated docs per chunk : 655360

Totals
 data : 381.47Mb docs : 10000102 chunks : 16
 Shard Shard1 contains 47.57% data, 47.57% docs in cluster, avg obj size on shard : 40b
 Shard Shard2 contains 52.42% data, 52.42% docs in cluster, avg obj size on shard : 40b


# migration中の件数(約20秒ごと)(コマンドは一部省略)
# indexを張っていないnumberで検索
mongos> use ryooo
switched to db ryooo
mongos> b.test_humongous.find({ number : {$gt: 100,  $lt: 8000000} } ).count();
798969 ←開始時
798969
820015 ←ずれはじめ
828251
851267
・
(すべて正常値以上の値)
・
890386
840958
798969 ←終了時(開始時と同じ)




# ----------------------------------
# 次は、indexを張ってやればどうか。
# 初期化
use ryooo
db.test_humongous.drop()

# indexをはる
db.test_humongous.ensureIndex({number:1})

# 1,000万件のデータ投入
use ryooo
ins_humongous = function(){
  n = Math.random() * 100000000
  db.test_humongous.insert({number: parseInt(n)})
}
for (i = 0; i <= 10000000; i++) {
  ins_humongous()
}

# numberにindexがついている状態
mongos> db.test_humongous.stats()
{
 ・
 ・
 "indexSizes" : {
  "_id_" : 324464560,
  "number_1" : 356841520
 },
}

# ----------------------------------
# migration開始
# ----------------------------------
# 最初は799226件だった(コマンドは一部省略)
mongos> use ryooo
switched to db ryooo
mongos> db.test_humongous.find({ number : {$gt: 100,  $lt: 8000000}}).count();
799226 ←開始時
803179
809402
814710
・
(すべて正常値以上の値)
・
813520
802336
799226 ←終了時(開始時と同じ)



# 全件検索(コマンドは一部省略)
mongos> db.test_humongous.count()
10000001 ←開始時
10000001
10481154
10470561
10438490
・
(すべて正常値以上の値)
・
10215171
10067667
10000001 ←終了時(開始時と同じ)



# snapshot()しても結果は変わらず(コマンドは省略)
mongos> db.test_humongous.find().snapshot().count()
10013371 ←途中から気づいてとり始めた
10009113
10005426
・
(すべて正常値以上の値)
・
10222059
10092911
10000001 ←終了時(全件検索数と一致)



# シャードキーでの検索も同様にずれる。
# 1回目のmigrationでの計測では、初回の1回だけ異常値で後は正常値であった。
# 2回目のmigrationでの計測では、すべてのcountがずれた。
#   これはシャードキーでの検索ではglobalでなく、
#   対象のchunkが存在するシャードにのみ検索が走るため、
#   対象のchunkがいつmoveするかで結果が異なる。

# 1回目のmigration(コマンドは一部省略)
mongos> db.test_humongous.find({ _id : {$lt: ObjectId('4fad11b830e2c797dc8ec095')}}).count();
2966108 ←開始時
1810734
1810734
・
(すべて正常値)
・
1810734
1810734 ←終了時

# 2回目のmigration
mongos> db.test_humongous.find({ _id : {$lt: ObjectId('4fadb6a76d5f062fe7f155eb')}}).count();
6022486 ←開始時
6310732
6966093
7621454
6719822
5753037
6210336
5592768
5655372
5233997
5000011 ←終了時

やはりProduction環境ではauto-shardingを停止した方が良いな。

0 件のコメント:

コメントを投稿