LoginSignup
8
7

More than 3 years have passed since last update.

MongoDBの同期の仕組みと知っておくべき注意点

Posted at

はじめに

MongoDBでReplica Setの構成を組むと、メンバー間でデータの同期が行われます。
同期の仕組みを理解していないと、障害が発生した時の対応を誤ってしまうことがあるので、ここにまとめておきます。

環境

バージョン
$ mongod --version
db version v4.0.8

同期の仕組み

簡単にまとめると下記の通りです。

  • Primaryで書き込みが実行されると、そのオペレーションをlocal.oplog.rsというcollectionに保存する。
  • Secondaryは、Primaryからlocal.oplog.rsをコピーする。
  • Secondaryは、コピーしたlocal.oplog.rsを順次実行する。

データをコピーしているのではなく、オペレーションをコピーしているというところが味噌です。

oplogの容量制限

oplogはcapped collectionという容量に制限のあるcollectionです。
つまり、長時間のダウンでoplogが保存されている期間を過ぎた場合は、同期が不可能になってしまいます(STALE状態)。
こうなってしまうと、Initial Syncでゼロから同期を始めなければいけなくなります。

oplogのサイズや保存されている期間は下記コマンドで確認できます。

PRIMARY> rs.printReplicationInfo()
configured oplog size:   2574.97265625MB
log length start to end: 11667867secs (3241.07hrs)
oplog first event time:  Wed Apr 03 2019 16:54:58 GMT+0900 (JST)
oplog last event time:   Fri Aug 16 2019 17:59:25 GMT+0900 (JST)
now:                     Fri Aug 16 2019 17:59:27 GMT+0900 (JST)

保存期間が短く、長時間ダウンで同期が不可能になってしまう危険性がある場合は、oplogの容量を大きくすることで対応ができます。

下記コマンドでoplogの容量を変更できます(単位はMB)。

PRIMARY> db.adminCommand({ replSetResizeOplog: 1, size: 3000 })

lastStableCheckpointTimestamp (ver.4.0〜)

Replica Set全てが同期された最終時刻のことです。
下記コマンドで確認できます。

PRIMARY> db.adminCommand( { replSetGetStatus : 1 } )
〜
"lastStableCheckpointTimestamp" : Timestamp(1565946285, 1),
〜

Replica SetのメンバーがInitial Sync等で同期していたり、ダウンしていたりすると、この値は長時間更新されません。これは注意が必要です(詳細は下記Recoveryで)。

lastStableCheckpointTimestamp

Recovery ※注意

Replica Setメンバーは、起動時にRecoveryが実行されます。
公式には見当たりませんでしたが、どうやらlastStableCheckpointTimestamp 〜 oplogの最終更新日までのoplogを実行しているようです。

起動時、Recoveryが実行された時のログ
[initandlisten] Recovering from stable timestamp: Timestamp(1565241749, 5) (top of oplog: { ts: Timestamp(1565281045, 1), t: 61 }, appliedThrough: { ts: Timestamp(0, 0), t: -1 }, TruncateAfter: Timestamp(0, 0))
[initandlisten] Starting recovery oplog application at the stable timestamp: Timestamp(1565241749, 5)
[initandlisten] Replaying stored operations from { : Timestamp(1565241749, 5) } (exclusive) to { : Timestamp(1565281045, 1) } (inclusive).

Initial Sync中はlastStableCheckpointTimestampが更新されておらず、その間にレプリカセットのメンバーを再起動すると、Recoveryが走り、Initial Sync開始時刻から現在までのoplogが実行され、完了するまで正常起動しないということが起きます。
データ量の多いDBだとInitial Syncに長時間かかることがあるので、その間に下手に再起動をかけると、oplog実行待ちの間サービスが停止してしまう、なんてことになりかねないので注意が必要です。
また、Secondaryがダウンしている状態で、Primaryを再起動すると、Secondaryがダウンしている期間中のoplogがPrimaryで実行されてしまいます。これも同様に注意が必要です。SecondaryがダウンしたままPrimaryを再起動したい場合は、そのSecondaryをメンバーから外しておくという操作が必要です。

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7