この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、菊池です。
今回は小ネタです。以前、MongoDBのレプリカセットパターンを紹介しました。
MongoDBのレプリカセットでは、AZ障害などにより過半数のノードで障害が発生すると、残存ノードでプライマリへの昇格が不可能になるため、書き込みを受け付けられなくなります。
MongoDB Enterprise s0:SECONDARY> rs.status()
{
"set" : "s0",
"date" : ISODate("2017-07-31T10:01:57.956Z"),
"myState" : 2,
"term" : NumberLong(13),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"appliedOpTime" : {
"ts" : Timestamp(1501495292, 1),
"t" : NumberLong(13)
},
"durableOpTime" : {
"ts" : Timestamp(1501495292, 1),
"t" : NumberLong(13)
}
},
"members" : [
{
"_id" : 0,
"name" : "mongo0:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 128,
"optime" : {
"ts" : Timestamp(1501495292, 1),
"t" : NumberLong(13)
},
"optimeDate" : ISODate("2017-07-31T10:01:32Z"),
"infoMessage" : "could not find member to sync from",
"configVersion" : 7,
"self" : true
},
{
"_id" : 1,
"name" : "mongo1:27017",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDurable" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
"optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate("2017-07-31T10:01:57.618Z"),
"lastHeartbeatRecv" : ISODate("2017-07-31T10:01:27.077Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "Connection refused",
"configVersion" : -1
},
{
"_id" : 2,
"name" : "mongo2:27017",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDurable" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
"optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate("2017-07-31T10:01:57.642Z"),
"lastHeartbeatRecv" : ISODate("2017-07-31T10:01:05.867Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "Connection refused",
"configVersion" : -1
}
],
"ok" : 1
}
ここの状況で書き込みを可能にするためには、残存ノードのうち1つをレプリカセットから切り離し、スタンドアローンで起動します。
設定ファイルのレプリカセットの部分をコメントアウトし、再起動します。
$ cat /etc/mongod.conf
net:
port: 27017
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
storage:
dbPath: /data
processManagement:
fork: true
pidFilePath: /var/run/mongodb/mongod.pid
#replication:
# replSetName: s0
$ sudo systemctl restart mongod
この状態では、書き込みが可能になります。
$ mongo
MongoDB shell version v3.4.6
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.6
MongoDB Enterprise > db.user.insert({name:"hoge"});
WriteResult({ "nInserted" : 1 })
まとめ
以上です。
二重障害などでPrimary昇格が不能になった際に、緊急でサービスを復旧させる必要がある場合にはこのような手段もあります。ただし、分断された過半数側のノードでも書き込みが発生してしまうと、不整合な状態となりますので注意しましょう。