Кластер MongoDB и чтение со вторичного, когда первичный не работает

Это не основной вопрос, просто спрашивая о кластере монго. На мой взгляд, это не дубликат. У меня есть кластер mongodb с 3 узлами, и мой URL-адрес представляет собой что-то вроде следующих строк в файле конфигурации PlayFramework.

mongodb.uri = "mongodb://mongodb1:27017,mongodb2:27017,mongodb3:27017/myproj"

По умолчанию, когда реплика настроена, все операции чтения и записи происходят только на основном сервере, и это то, что я хочу. Однако я хочу, чтобы чтение шло к вторичному, когда не осталось основного, то есть когда 2 узла выходят из строя, не останется основного и только один дополнительный.

Я не хочу изменять свой код для достижения этого для каждого запроса на чтение. Я пробовал следующее на вторичном узле, но это не помогает

db.getMongo().setReadPref('primaryPreferred')

Что именно мне нужно сделать, чтобы это сработало?


person curiousengineer    schedule 06.07.2017    source источник
comment
Если два из трех узлов выйдут из строя, то набор реплик будет просто недоступен для работы до дальнейшего вмешательства. На всю тему есть обширный справочный раздел. Проиндексировано в Репликация   -  person Neil Lunn    schedule 06.07.2017
comment
Не совсем верно. В наборе реплик не будет первичного согласия, и я это знаю. Вторичный все равно будет. Если я вслепую отмечу rs.slaveOK(), я все еще могу читать его, но я не хочу этого делать. Я хочу, чтобы оставшийся вторичный сервер разрешал чтение только тогда, когда нет основного   -  person curiousengineer    schedule 06.07.2017
comment
С точки зрения кода вашего приложения это правда. Все остальное по этому вопросу требует вмешательства администратора баз данных. И поэтому становится вопросом, более подходящим для dba.stackexchange.com, потому что это не имеет ничего общего с кодом приложения. Аналогичным образом вы также можете вручную продвигать оставшийся узел. Но опять же, проблема DBA. Кодовый ответ - это не должно волновать.   -  person Neil Lunn    schedule 06.07.2017
comment
либо вы не понимаете, о чем я спрашиваю, либо мне нужно перефразировать свой вопрос. Цель состоит не в том, чтобы использовать ручное вмешательство, а в том, чтобы использовать параметры ?readPreference=secondary&maxStalenessSeconds=   -  person curiousengineer    schedule 06.07.2017
comment
А вам говорят, что нельзя. Вы должны вручную вмешаться. Как это трудно понять? На самом деле вы должны сосредоточиться на том, чтобы не позволить большинству узлов выйти из строя.   -  person Neil Lunn    schedule 06.07.2017
comment
Если вы намерены читать только с вторичного устройства, если основное недоступно, primaryPreferred предпочтение чтения (с необязательным maxStalenessSeconds в MongoDB 3.4+) — это то, что вам нужно. Однако вам необходимо установить этот параметр с точки зрения драйвера или приложения (т. е. в конфигурации или приложении PlayFramework). Установка предпочтения чтения в оболочке mongo влияет только на текущий сеанс оболочки.   -  person Stennie    schedule 06.07.2017
comment
спасибо @Stennie, я попытался немного почитать о том, как это сделать в игре, и попробовал следующее, но даже тогда он хочет, чтобы первичный существовал. Любые мысли о том, что может быть не так в приведенном ниже синтаксисе? mongodb.uri = mongodb://mongodb1:27017,mongodb2:27017,mongodb3:27017/myproj?readPreference=secondary&maxStalenessSeconds=180   -  person curiousengineer    schedule 06.07.2017
comment
Похоже, вам не хватает параметра replicaSet=... (который должен соответствовать настроенному имени набора реплик), поэтому вы, вероятно, получаете прямое подключение к первому указанному хосту, а не подключение набора реплик с отработкой отказа. Какой драйвер и версию MongoDB вы используете и какую версию Play Framework? Для получения дополнительной информации о формате и параметрах строки подключения MongoDB см.: docs.mongodb.com/ руководство/ссылка/строка-подключения.   -  person Stennie    schedule 06.07.2017
comment
Значение replicaSet — это имя/_id набора реплик, которые должны быть общими для всех членов одного набора: docs.mongodb.com/manual/reference/replica-configuration/. Список членов набора реплик, который вы указываете в строке подключения, — это начальный список, используемый для обнаружения текущей конфигурации набора реплик (но только если вы подключаетесь в режиме набора реплик, указав имя replicaSet). Можете ли вы подтвердить версии используемых вами драйверов PlayFramework и MongoDB? Это упростит проверку того, что мы говорим об одной и той же конфигурации.   -  person Stennie    schedule 06.07.2017
comment
да, я понял, пытаюсь сейчас, вы правы в своих предложениях, однако мне интересно, является ли это обязательным параметром, на основе документов мне это не кажется. Могу я спросить @Stennie, почему вы считаете обязательным наличие replicaSet= в URL?   -  person curiousengineer    schedule 06.07.2017
comment
вот как это у меня сейчас, прежде чем тестировать, что вы думаете об этом mongodb.uri = mongodb://mongodb1:27017,mongodb2:27017,mongodb3:27017/myproj? создайте мой кластер следующим образом rs.initiate({ _id: mongocluster, member: [{ _id: 1, host: mongodb1:27017}, { _id: 2, host: mongodb2:27017}, { _id: 3, host: mongodb3: 27017 }], настройки: {getLastErrorDefaults: {w: большинство, wtimeout: 30000 }}}) так что это должно работать сейчас URL-адрес, который я даю?   -  person curiousengineer    schedule 06.07.2017


Ответы (1)


Я не хочу изменять свой код для достижения этого для каждого запроса на чтение. Я попробовал следующее на вторичном узле, но это не помогает:

db.getMongo().setReadPref('primaryPreferred')

Вы находитесь на правильном пути с настройками чтения, но вам нужно установить это в строке подключения или драйвере. Настройка предпочтения чтения в оболочке mongo влияет только на текущий сеанс оболочки и не влияет на удаленные подключения.

mongodb.uri = "mongodb://mongodb1:27017,mongodb2:27017,mongodb3:27017/myproj"

Вам необходимо добавить некоторые дополнительные параметры в соответствии с форматом URI соединительной строки MongoDB:

  • (обязательно) Параметр replicaSet=... указывает, что Драйвер должен использовать режим подключения «набор реплик», а не режим прямого подключения по умолчанию. Этот параметр включает мониторинг набора реплик, предпочтения чтения и обнаружение изменений топологии. Предоставленное имя набора реплик должно совпадать с именем набора реплик. настроен для вашего развертывания. Для получения полной информации о поведении при подключении, ожидаемом для официально поддерживаемых драйверов MongoDB, см. -and-monitoring.rst" rel="nofollow noreferrer">Обнаружение и мониторинг серверов (SDAM). обоснование содержит ответы на распространенные вопросы о выбранном подходе.
  • (обязательно) Параметр readPreference=primaryPreferred указывает на предпочтение чтения с первичного, но использования вторичного, если первичный недоступен.
  • (необязательно) В MongoDB 3.4+ вы можете указать maxStalenessSeconds=..., который ограничивает максимальную задержку репликации (или устаревание) при использовании вторичного предпочтения чтения. По умолчанию максимальное устаревание отсутствует, поэтому драйвер не будет учитывать задержку репликации при выборе вторичного хранилища на основе предпочтения чтения. Если вы намерены использовать primaryPreferred в качестве варианта аварийного переключения для чтения, я бы с осторожностью устанавливал максимальное устаревание: вам нужно убедиться, что у вас есть хотя бы один вторичный сервер с допустимым устареванием.

Итак, если предположить, что имя набора реплик mongocluster и база данных myproj, предлагаемая строка подключения будет следующей:

mongodb://mongodb1:27017,mongodb2:27017,mongodb3:27017/mypr‌oj?replicaSet=‌mongocluster&readPreference=primaryPreferred
person Stennie    schedule 06.07.2017
comment
Привет @Stennie, я вижу это в своих журналах игр, значит ли это, что мне не повезло? reactivemongo.api.MongoDriver — некоторые параметры были проигнорированы, потому что они (пока) не поддерживаются: replicaSet. Кроме того, я попытался прочитать ссылку, чтобы понять, почему действительно нужен replicaSet, но не очень понятно, почему. В любом случае, я предполагаю, что ваше предложение является обязательным, но игнорируется ли оно игровым фреймворком? - person curiousengineer; 06.07.2017
comment
@curiousengineer Какой драйвер и версию MongoDB вы используете и какую версию Play Framework? Что касается подключения набора реплик, разница заключается в том, как драйвер обнаруживает и контролирует топологию. Спецификация SDAM требует серьезного чтения, но на высоком уровне есть три категории топологий подключения (автономный, набор реплик или сегментированный). Без параметра replicaSet вы обычно подключаетесь в режиме Standalone к первому указанному хосту (т. е. нет обнаружения или мониторинга конфигурации набора реплик и нет поддержки предпочтений чтения). - person Stennie; 06.07.2017
comment
Я использую Mongodb 3.4 (образ контейнера докеров). Моя игровая версия — addSbtPlugin (com.typesafe.play % sbt-plugin % 2.5.10), поэтому я предполагаю, что это 2.5.10. Когда вы говорите версию драйвера Mongodb, я не уверен, откуда я это знаю. Но так как мы используем реактивный монго, вот зависимость для этого org.reactivemongo %%play2-reactivemongo% 0.12.0 - person curiousengineer; 06.07.2017