В репликации mongodb 3.0, как происходят выборы, когда вторичный сервер выходит из строя
Ситуация: у меня установлена репликация MongoDB на двух компьютерах.
- Один компьютер - это сервер, который содержит основной узел и арбитр. Этот сервер является живым сервером и всегда включен. Это локальный IP, который используется в репликации
192.168.0.4
, - Второй - это компьютер, на котором расположен вторичный узел и который включен несколько часов в день. Это локальный IP, который используется в репликации
192.168.0.5
,
Мои ожидания: я хотел, чтобы живой сервер был главной точкой взаимодействия данных моего приложения, независимо от состояния ПК (независимо от того, доступен ли он или нет, поскольку ПК является вторичным), поэтому я хотел убедиться, что узел этого сервера всегда первичен.
Следующее является результатом rs.config()
:
liveSet:PRIMARY> rs.config()
{
"_id" : "liveSet",
"version" : 2,
"members" : [
{
"_id" : 0,
"host" : "192.168.0.4:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 10,
"tags" : {
},
"slaveDelay" : 0,
"votes" : 1
},
{
"_id" : 1,
"host" : "192.168.0.5:5051",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : 0,
"votes" : 1
},
{
"_id" : 2,
"host" : "192.168.0.4:5052",
"arbiterOnly" : true,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : 0,
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatTimeoutSecs" : 10,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
}
}
}
Также я установил для WiredTiger механизм хранения, если это имеет значение.
Что я на самом деле получаю, и проблема: когда я выключаю ПК или убиваю его процесс mongod, то узел на сервере становится вторичным.
Ниже приведен вывод сервера, когда я уничтожил процесс mongod на ПК, когда он подключен к оболочке основного узла:
liveSet:PRIMARY>
2015-11-29T10:46:29.471+0430 I NETWORK Socket recv() errno:10053 An established connection was aborted by the software in your host machine. 127.0.0.1:27017
2015-11-29T10:46:29.473+0430 I NETWORK SocketException: remote: 127.0.0.1:27017 error: 9001 socket exception [RECV_ERROR] server [127.0.0.1:27017]
2015-11-29T10:46:29.475+0430 I NETWORK DBClientCursor::init call() failed
2015-11-29T10:46:29.479+0430 I NETWORK trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2015-11-29T10:46:29.481+0430 I NETWORK reconnect 127.0.0.1:27017 (127.0.0.1) ok
liveSet:SECONDARY>
У меня есть два сомнения:
- Учитывая эту часть документации MongoDB:
Наборы реплик используют выборы, чтобы определить, какой элемент набора станет основным. Выборы происходят после инициирования набора реплик, а также каждый раз, когда первичный становится недоступным.
Выборы происходят, когда первичная недоступна (или во время инициации, однако это часть не касается нашего случая), но первичная была всегда доступна, поэтому, почему выборы происходят.
- Учитывая эту часть той же документации:
Если большая часть набора реплик недоступна или недоступна, набор реплик не может принимать записи, и все остальные элементы становятся доступными только для чтения.
Учитывая, что часть "члены становятся доступными только для чтения", у меня есть два узла вверх против одного вниз, поэтому это не должно влиять на нашу репликацию.
Теперь мой вопрос: как сохранить узел на сервере в качестве основного, когда узел на ПК недоступен?
Обновление: это вывод rs.status()
,
Благодаря Ван Бахтияру, теперь это делает поведение очевидным, поскольку арбитр не был доступен.
liveSet:PRIMARY> rs.status()
{
"set" : "liveSet",
"date" : ISODate("2015-11-30T04:33:03.864Z"),
"myState" : 1,
"members" : [
{
"_id" : 0,
"name" : "192.168.0.4:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1807553,
"optime" : Timestamp(1448796026, 1),
"optimeDate" : ISODate("2015-11-29T11:20:26Z"),
"electionTime" : Timestamp(1448857488, 1),
"electionDate" : ISODate("2015-11-30T04:24:48Z"),
"configVersion" : 2,
"self" : true
},
{
"_id" : 1,
"name" : "192.168.0.5:5051",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 496,
"optime" : Timestamp(1448796026, 1),
"optimeDate" : ISODate("2015-11-29T11:20:26Z"),
"lastHeartbeat" : ISODate("2015-11-30T04:33:03.708Z"),
"lastHeartbeatRecv" : ISODate("2015-11-30T04:33:02.451Z"),
"pingMs" : 1,
"configVersion" : 2
},
{
"_id" : 2,
"name" : "192.168.0.4:5052",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"lastHeartbeat" : ISODate("2015-11-30T04:33:00.008Z"),
"lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
"configVersion" : -1
}
],
"ok" : 1
}
liveSet:PRIMARY>
1 ответ
Как указано в документации, если большая часть набора реплик недоступна или недоступна, набор реплик не может принимать записи, и все остальные элементы становятся доступными только для чтения.
В этом случае первичный должен уйти в отставку, если арбитр и вторичный не достижимы. rs.status()
должен быть в состоянии определить здоровье членов реплики.
Также следует следить за размером основного оплога. Размер оплога определяет, как долго член набора реплик может быть недоступен и все еще сможет наверстать упущенное, когда он вернется в оперативный режим. Чем больше размер оплога, тем дольше вы можете справиться с тем, что участник не работает, так как оплог может содержать больше операций. Если он слишком сильно отстает, необходимо повторно синхронизировать элемент, удалив его файлы данных и выполнив первоначальную синхронизацию.
См. Проверьте размер Oplog для получения дополнительной информации.
С Уважением,
Ван.