概要
シャード構成の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