Shardingの管理

based on v33 (2010/12/30 更新) - オリジナル

ここでは、shardingクラスターから情報を取得するためのコマンドを紹介します。

shardingクラスターを設定するためには、 Shardingの設定 を参照してください。

shardクラスターの確認

 
// mongosプロセスにつないでいるか、
// mongodプロセスに直接つないでいるかの確認
> db.runCommand({ isdbgrid : 1});

// mongosに接続している場合、このコマンドは、 { ismaster: 0.0, msg: "isdbgrid" } を返します。
> db.runCommand({ismaster:1})

存在するShardのリスト表示

> db.runCommand({ listshards : 1});
{"servers" : 
[{"_id" : ObjectId( "4a9d40c981ba1487ccfaa634") , 
"host" : "localhost:10000"}, 
{"_id" : ObjectId( "4a9d40df81ba1487ccfaa635") , 
"host" : "localhost:10001"} 
], 
"ok" : 1 
} 

どのデータベースがshard化されているかのリスト表示

ここで、mongos 経由でconfigデータベースに対してクエリを実行する方法を示します。この getSisterDB コマンドはconfigデータベースを取得するために使われます。

> config = db.getSisterDB("config") 
> config.system.namespaces.find() 

shardingの詳細を確認

 
> use admin
> db.printShardingStatus());

// localhost上の基本的なsharding configurationを表示します
sharding version: { "_id" : 1, "version" : 2 }
shards:
{ "_id" : ObjectId("4bd9ae3e0a2e26420e556876"), "host" : "localhost:30001" }
{ "_id" : ObjectId("4bd9ae420a2e26420e556877"), "host" : "localhost:30002" }
{ "_id" : ObjectId("4bd9ae460a2e26420e556878"), "host" : "localhost:30003" }

databases:
{ "name" : "admin", "partitioned" : false, 
"primary" : "localhost:20001", 
"_id" : ObjectId("4bd9add2c0302e394c6844b6") }
my chunks

{ "name" : "foo", "partitioned" : true,
"primary" : "localhost:30002", 
"sharded" : { "foo.foo" : { "key" : { "_id" : 1 }, "unique" : false } },
"_id" : ObjectId("4bd9ae60c0302e394c6844b7") }
my chunks
foo.foo { "_id" : { $minKey : 1 } } -->> { "_id" : { $maxKey : 1 } } 
on : localhost:30002 { "t" : 1272557259000, "i" : 1 }

printShardingStatus コマンドの出力に注目してください。 最初にこのクラスタを含む3つのshardの場所が出ています。次に、このクラスタがあるいくつかのデータベースが出ます。

最初のデータベースは、分割されていないadminデータベースです。 primary フィールドはデータベースの場所を指し、adminデータベースの場合には、port 20001で動いているconfigサーバになります。

二つめのデータベースは、 分割されて いることがわかります。 また、shardのキーと場所、そしてこのパーティションに含まれるchunkのレンジがわかります。 foo データベースにはデータがまだ何もないので、一つのchunkしかありません。この一つのchunkがshardキーの全体のレンジを含みます

バランシング

バランサーは全てのクラスターサーバーにおいてchunkの数を均等に保つためのバックグラウンドタスクです。バランシングのアクティビティはクエリーに対して透過的です。言い換えれば、あなたのアプリケーションは(バランシングのために)移動しているデータについて知る必要も気にかける必要も無いという事です。

それを可能にするために、バランサーはいつ・どれくらいのサイズのデータを移動すべきなのかに注意しています。それでは初めにどのようにして移動するのか見ていく事にしましょう。移動単位はchunkです。安定した状態では、chunkのデータサイズは100-200MBの範囲内にあります。この範囲はデータを一度に移動する際の適切な値として設定されています。この範囲以上の値だとマイグレーションに時間がかかり、クエリーのレスポンス時間に大きなばらつきがあることを考慮しないといけないかもしれません。これ以下だと移動のオーバーヘッドが大きくなってしまいます。

バランサーはchunkの不均衡数を監視しており、それが閾値を超えた時に実際に移動を実行します。現実的に、ヒューリスティクス的に良いとされる不均衡数は最新にロードされたshardと最もロードされるshardとのchunk数の差が8である時です。(この値は任意の値にできます。)

一度バランサーが動作すると、chunkの再分配が、2つのshard間のchunk数の差異が2になるまで行われます。

良くある質問に、なぜ与えられたコレクションが均等になっていないのかというのがあります。その多くの場合の答えとして、バランシングの必要が無い事が挙げられます。もしchunkの差異が十分小さければ、再分配は行われません。実際に十分大きなコレクションであり、かつ(機械的な)バランシングのオーバーヘッドコストがアプリケーションの扱うデータの量にに比べて十分小さいことを暗黙の仮定に置いています。もし数学をやっている人なら、バランシングを行うかどうかを判断する閾値は、あなたのラップトップ上の実験では起こりえないことに気付くはずです。

他の答えの可能性として、バランサーが動作していない事が挙げられます。バランシングタスクはクラスター内のクエリールーターである任意のmongosによって発生します。複数のクエリールーターがある場合においては、どのmongosがバランシングタスクの責任を負うかを決定するメカニズムが存在します。バランサーとしてのmongosの振る舞いは、configデータベースの"locks"コレクションへのドキュメントinsertによって"lock"されます。このlockしているmongosの状態は1となっています。

lock状態であるかを確認するには、

 // mongos に接続します
> use config 
> db.locks.find( { _id : "balancer" } ) 

このコマンドの典型的な出力は次のようになります:

{ "_id" : "balancer", "process" : "guaruja:1292810611:1804289383", "state" : 1, "ts" : ObjectId("4d0f872630c42d1978be8a2e"), "when" : "Mon Dec 20 2010 11:41:10 GMT-0500 (EST)", "who" : "guaruja:1292810611:1804289383:Balancer:846930886", "why" : "doing balance round" } 

この出力には少なくとも3つの注目点があります。1つ目は state 属性が1であることで、これはlockされている事を意味しています。バランサーがアクティブであることを確認できています。2つ目は when 属性がMonday, December the 20thからバランサーが動作していることを意味していることです。3つ目は who 属性が"guaruja"マシン上でコールされている事です。

バランサーが実際に動作していることをチェックするために、対象マシンのmongosのログを見ます。バランサーは "[Balancer]" のプレフィックスがついた行を出力します。

Mon Dec 20 11:53:00 [Balancer] chose [shard0001] to [shard0000] { _id: "test.foo-_id_52.0", lastmod: Timestamp 2000|1, ns: "test.foo", min: { _id: 52.0 }, max: { _id: 105.0 }, shard: "shard0001" } 

この行では、バランサーがchunk _id:[52..105) をshard0001からshard0000への移動を決定した事を述べています。この双方のmongodのログではどのようにしてこの移動が行われたのかの詳細なエントリーがあります。

もしメンテナンスのために一時的にバランサーの動作を呈しさせたい場合は、config dbのコレクションセッティングを書き換えます:

// connect to mongos 
> use config 
> db.settings.update( { _id: "balancer" }, { $set : { stopped: true } } , true ); 

このコマンドを実行すると、バランサーとして動作するmongosでは "[Balancer]" のエントリーが無くなります。

Mon Dec 20 11:57:35 "[Balancer]" skipping balancing round because balancing is disabled 

再度動作させる場合には stopped をfalseにしてupdateします。

chunk migrationのより詳細な情報とコマンドを確認するにはMoving Chunksを参照して下さい。

Chunkサイズについて

mongoDBのshardingは*range partitioning* をベースにしています。chunkは閾値を超えるサイズに達した時に自動的に分割されます。この閾値は変化しますが、大雑把に言うと安定した状態における、最大chunkサイズとその半分の間に設定されます。そしてデフォルトの最大chunkサイズは200MBとなっています。(これはインデックスを含まないコレクション内のオブジェクトの合計です。)

chunkサイズについては活発に議論されています。

データが移動されると、クエリールーターであるmongosのいくつかの状態がリセットされます。今まで移動される前のshardにヒットしていたクエリーは新しいshardにヒットする必要があります。この状態のリセットは自由には行われ無いので、chunkの移動がそれほど頻繁に起こらない事を期待しています。しかし実際の移動は移動するキーの数に比例してコストが増大することになります。

もしプロダクションサイトにおいて、デフォルトのchunkサイズを変更したい場合は、mongosの --maxSize パラメータを設定します。もしデフォルトより小さいサイズを設定した場合には、現状では新しいドキュメントのinsertかupdateがあった時にそれがトリガーとなって分割が実行されますので、多少時間がかかる事に注意して下さい。

chunkの分割のより詳しい情報やコマンドを確認したい場合はSplitting Chunksを参照して下さい。


Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

IF YOU HAVE A QUESTION, POST IT TO THE USER GROUP.

These pages are fine for comments, but for questions, your best bet will always be the MongoDB User Group.

blog comments powered by Disqus