概要
シャード構成のMongoDBがチャンクの分割に失敗し、一定サイズを超えるとjumboというフラグが付きます。
普通の環境ではそうそう起きませんが、大量のドキュメントを扱っているとたまに発生します。
今回はそれの解消方法を紹介します。
環境
- MongoDB 3.2.17
どういう状態か
シャード構成にしてシャードキーを設定することで本来分散するようになりますが、状態を確認した時に
mongos> sh.status()
...
balancer:
Currently enabled: yes
Currently running: unknown
Collections with active migrations:
balancer started at Thu Apr 18 2019 23:55:15 GMT+0900 (JST)
test.foo started at Thu Apr 18 2019 23:55:16 GMT+0900 (JST)
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
1296 : Failed with error 'aborted', from shard_4 to shard_1
1296 : Failed with error 'aborted', from shard_2 to shard_1
11669 : Failed with error 'aborted', from shard_0 to shard_1
...
このようにmigrationに失敗している時はjumboチャンクが発生している可能性が高いです。
Jumboフラグの確認方法
sh.status(true)と、引数を付けると確認できるようになります。
--- Sharding Status ---
sharding version: {
...
}
shards:
...
databases:
...
test.foo
shard key: { "x" : 1 }
chunks:
shard_1 2
shard_2 2
{ "x" : { "$minKey" : 1 } } -->> { "x" : 1 } on : shard_2 Timestamp(2, 0)
{ "x" : 1 } -->> { "x" : 2 } on : shard_1 Timestamp(3, 1)
{ "x" : 2 } -->> { "x" : 4 } on : shard_1 Timestamp(2, 2) jumbo
{ "x" : 4 } -->> { "x" : { "$maxKey" : 1 } } on : shard_2 Timestamp(3, 0)
jumboとついてるチャンクが問題のチャンクです。
解決方法
jumboフラグのたったチャンクを分割する場合はsh.splitAt()かsh.splitFind()で対処しますが、おすすめは後者です。
sh.splitAt()は自分でどこで分割するかを決める必要がありますが、sh.splitFind()の方はそのチャンクをちょうど半分に分割してくれます。
今回jumboフラグが発生しているのはtest.fooコレクションの
{ "x" : 2 } -->> { "x" : 4 } on : shard-a Timestamp(2, 2) jumbo
なので、
mongos> sh.splitFind("test.foo", { "x" : 2 })
とするとチャンクを半分に分割してくれます。
結果
全て分割しおえ、jumboフラグが消えるとmigrationが再び成功するようになります。
Migration Results for the last 24 hours:
35 : Success
16 : Failed with error 'aborted', from shard_0 to shard_1
その他
jumboフラグを解消してもmigrationが失敗する
先程jumboフラグを解消してもうまくマイグレーションできない時がありました。
mongos> sh.status()
...
balancer:
Currently enabled: yes
Currently running: unknown
Collections with active migrations:
balancer started at Thu Apr 18 2019 23:55:15 GMT+0900 (JST)
test.foo started at Thu Apr 18 2019 23:55:16 GMT+0900 (JST)
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
1296 : Failed with error 'aborted', from shard_4 to shard_1
1296 : Failed with error 'aborted', from shard_2 to shard_1
11669 : Failed with error 'aborted', from shard_0 to shard_1
...
どうやらshard_1への移動が失敗しています。
ログを確認
一番多くコケている
11669 : Failed with error 'aborted', from shard_0 to shard_1
に注目して、それぞれのログを見てみると
shard_0
2019-04-18T19:58:44.549+0000 W SHARDING [conn12196576] moveChunk failed to engage TO-shard in the data transfer: :: caused by :: UnknownError: can't accept new chunks because there are still 4 deletes from previous migration
どうやら移動先のshard_1で削除が完了していないせいで止まっているとのこと。
shard_1
2019-04-17T21:47:20.178+0000 I SHARDING [RangeDeleter] waiting for open cursors before removing range [{ id: "2222btjnzfbztmmemaqpleldm" }, { id: "27jbcecxfjhzppixqmmy6ycsq" }) in test.bar, elapsed secs: 9658405, cursor ids: [228218372824, 228812226465, 231274992792]
こんな感じのエラーが4つ出ていました。これがずっと止まっていた原因のようです。
解決方法
以下の手順で解決させます。
RangeDeleterエラーが出ているshard_1のPrimaryをstepdown(降格)させる- Secondaryに切り替わったらそのmongodを再起動(※昇格したPrimary側はそのままで大丈夫です)
これで解消されます。migration自体は1のstepdownで解消されますが、それだけだとSecondaryに切り替わった元のPrimaryの状態が完全に直ってないので再起動してください。
結果
Successの表示が出てくるようになります。
balancer:
Currently enabled: yes
Currently running: unknown
Collections with active migrations:
test.foo started at Fri Apr 19 2019 10:05:04 GMT+0900 (JST)
balancer started at Fri Apr 19 2019 10:04:01 GMT+0900 (JST)
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
8 : Success
11655 : Failed with error 'aborted', from shard_0 to shard_1
1296 : Failed with error 'aborted', from shard_4 to shard_1
1296 : Failed with error 'aborted', from shard_2 to shard_1