Где mongodb стоит в теореме CAP?

121

Куда бы я ни посмотрел, я вижу, что MongoDB - это CP. Но когда я копаюсь, я вижу, что в конечном итоге это согласуется. Это CP, когда вы используете safe = true? Если да, значит ли это, что когда я пишу с safe = true, все реплики будут обновлены до получения результата?

Глуз
источник

Ответы:

104

MongoDB по умолчанию строго согласован - если вы выполняете запись, а затем выполняете чтение, при условии, что запись была успешной, вы всегда сможете прочитать результат только что прочитанной записи. Это связано с тем, что MongoDB - это система с одним главным сервером, и все операции чтения по умолчанию идут в основную. Если вы дополнительно разрешите чтение из вторичных источников, тогда MongoDB в конечном итоге станет согласованным, где можно будет прочитать устаревшие результаты.

MongoDB также обеспечивает высокую доступность за счет автоматического переключения при отказе в наборах реплик: http://www.mongodb.org/display/DOCS/Replica+Sets

stbrody
источник
13
Согласно aphyr.com/posts/322-call-me-maybe-mongodb-stale-reads, даже если вы читаете с основного узла в наборе реплик, вы можете получить устаревшие или грязные данные. Так является ли MongoDB устойчивым?
Майк Аргириу,
3
Потрясающие эксперименты Кайла. Он действительно охотится на монго. Интересно, есть ли производственные системы, например, использующие MongoDB для выполнения платежных транзакций? Если это просто личный веб-сайт, кого тогда волнует строгая согласованность.
Синь
5
Для справки: MongoDB v3.4 прошла тест, разработанный Кайлом, так что да, MongoDB полностью согласован, даже с ReplicaSet и Sharding: mongodb.com/mongodb-3.4-passes-jepsen-test
Максим
2
Этот ответ может быть слишком упрощенным, поскольку MongoDB может время от времени жертвовать доступностью в зависимости от конфигурации. JoCa's лучше объясняет ситуации, в которых он ведет себя CA / CP / AP
PaoloC
37

Я согласен с сообщением Luccas. Вы не можете просто сказать, что MongoDB - это CP / AP / CA, потому что на самом деле это компромисс между C, A и P, в зависимости от конфигурации базы данных / драйвера и типа аварии : вот визуальное резюме и ниже более подробное объяснение.

    Scenario                   | Main Focus | Description
    ---------------------------|------------|------------------------------------
    No partition               |     CA     | The system is available 
                               |            | and provides strong consistency
    ---------------------------|------------|------------------------------------
    partition,                 |     AP     | Not synchronized writes 
    majority connected         |            | from the old primary are ignored                
    ---------------------------|------------|------------------------------------
    partition,                 |     CP     | only read access is provided
    majority not connected     |            | to avoid separated and inconsistent systems

Последовательность:

MongoDB строго согласован, когда вы используете одно соединение или правильный уровень проблемы записи / чтения ( что будет стоить вам скорости выполнения ). Как только вы не соответствуете этим условиям (особенно когда вы читаете данные из вторичной реплики), MongoDB становится в конечном итоге согласованным.

Доступность:

MongoDB обеспечивает высокую доступность за счет наборов реплик . Как только первичный сервер выходит из строя или становится недоступным еще, вторичные серверы определят, что новый первичный сервер снова станет доступен. У этого есть недостаток: каждая запись, которая была выполнена старым первичным узлом, но не синхронизирована с вторичными, будет откатана и сохранена в файле отката, как только он повторно подключится к набору (старый первичный является вторичным сейчас). Таким образом, в этом случае некоторая согласованность принесена в жертву доступности.

Допуск раздела:

Благодаря использованию указанных наборов реплик MongoDB также достигает допустимости разделов: пока более половины серверов набора реплик подключены друг к другу, можно выбрать новый основной . Зачем? Чтобы гарантировать, что две отдельные сети не могут обе выбрать новую основную. Когда друг к другу подключено недостаточно вторичных устройств, вы все равно можете читать с них (но согласованность не гарантируется), но не записывать. Набор практически недоступен для единообразия.

Joca
источник
Итак, если я использую правильный уровень озабоченности записью / чтением, это означает, что все записи и чтения идут на первичный (если я правильно понял), так что именно делают вторичные? Просто сидеть там в режиме ожидания на случай, если основной выйдет из строя?
tomer.z
@ tomer.z, возможно, вы захотите прочитать этот раздел руководства: вы можете использовать вторичные файлы для чтения. Если вы используете «уровень чтения большинства», чтение будет считаться действительным, как только большинство участников подтвердят чтение. То же самое и с "большинством" уровня записи. Если вы используете уровень озабоченности «большинства» для обоих, то у вас есть согласованная база данных. Вы можете прочитать об этом больше в руководстве .
JoCa
18

Поскольку появилась блестящая новая статья , а также несколько потрясающих экспериментов Кайла в этой области, вы должны быть осторожны, маркируя MongoDB и другие базы данных как C или A.

Конечно, CAP помогает без лишних слов отследить, что преобладает в базе данных, но люди часто забывают, что C в CAP означает, например, атомарную согласованность (линеаризуемость). И мне было очень трудно понять это при попытке классифицировать. Таким образом, помимо того, что MongoDB обеспечивает сильную согласованность, это не означает, что это C. Таким образом, если кто-то делает эту классификацию, я также рекомендую более подробно рассказать о том, как это на самом деле работает, чтобы не оставлять сомнений.

Luccas
источник
10

Да, при использовании это CP safe=true. Это просто означает, что данные попали на главный диск. Если вы хотите убедиться, что он также прибыл на какую-то реплику, посмотрите параметр w = N, где N - количество реплик, на которых должны быть сохранены данные.

см. это и это для получения дополнительной информации.

Ян Призер
источник
3

Я не уверен насчет P для Mongo. Представьте себе ситуацию:

  • Ваша реплика разбивается на два раздела.
  • Обе стороны продолжают писать, так как были избраны новые хозяева.
  • Разделение разрешено - все серверы снова подключены
  • Что происходит, так это то, что выбирается новый мастер - тот, у которого самый высокий oplog, но данные от другого мастера возвращаются в общее состояние до раздела и сбрасываются в файл для ручного восстановления
  • все вторички догоняют нового хозяина

Проблема здесь в том, что размер файла дампа ограничен, и если у вас был раздел в течение длительного времени, вы можете потерять свои данные навсегда.

Вы можете сказать, что это маловероятно - да, если только в облаке это более распространено, чем можно подумать.

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

Если кто-нибудь знает, был ли рассмотрен этот сценарий в более поздних версиях Mongo, прокомментируйте! (Я давно не слежу за всем, что происходило ..)

kubal5003
источник
2
Протокол выборов MongoDB рассчитан на (не более) одного первичного голосования. Основной может быть избран (и поддержан) только строгим большинством настроенных голосующих членов набора реплик (n / 2 +1). В случае сетевого раздела только один раздел (с большинством голосующих членов) может выбрать первичный; предыдущий первичный раздел меньшинства уйдет в отставку и станет вторичным. Так всегда работали наборы реплик. В случае, если бывший первичный сервер принял записи, которые не были реплицированы, они будут отменены (сохранены на диск), когда этот член снова присоединится к набору реплик.
Stennie
2

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

sn.anurag
источник
2

MongoDB выбирает согласованность вместо доступности всякий раз, когда есть раздел. Это означает, что когда есть раздел (P), он выбирает согласованность (C) вместо доступности (A).

Чтобы понять это, давайте разберемся, как MongoDB работает с набором реплик. Набор реплик имеет единственный первичный узел. Единственный «безопасный» способ зафиксировать данные - это записать на этот узел, а затем ждать, пока эти данные будут зафиксированы на большинстве узлов в наборе. (вы увидите этот флаг для w = большинство при отправке записей)

Разделение может происходить в двух следующих случаях:

  • Когда основной узел выходит из строя: система становится недоступной, пока не будет выбран новый основной узел.
  • Когда основной узел теряет соединение со слишком большим количеством дополнительных узлов: система становится недоступной. Другие вторичные компании попытаются избрать новую первичную, и текущая первичная уйдет в отставку.

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

Раджниш Пракаш
источник
«Он перестанет принимать записи в систему до тех пор, пока не убедится, что может безопасно завершить эти записи». А как насчет чтения ? Будет ли он оставаться доступным для чтения в течение этого времени?
Джош
1

Mongodb обеспечивает согласованность и устойчивость к разделам .

В контексте распределенных (NoSQL) баз данных это означает, что всегда будет компромисс между согласованностью и доступностью. Это связано с тем, что распределенные системы всегда обязательно терпимы к разделам (т.е. она просто не была бы распределенной базой данных, если бы не была терпимой к разделам).

консистенция - система со временем станет согласованной. Рано или поздно данные распространятся повсюду, но система продолжит получать ввод и не проверяет согласованность каждой транзакции, прежде чем она перейдет к следующей.

Доступность - по умолчанию клиент Mongo DB (драйвер MongoDB) отправляет все запросы чтения / записи на ведущий / основной узел. Это делает систему согласованной, но недоступной из-за: - Если лидер отключается от кластера, то на выбор нового лидера уходит несколько секунд. Таким образом, делая его недоступным для записи и чтения в это время.

Сатакши Пандей
источник