Обеспечивает ли долговечность журнал MongoDB?

Даже если ведение журнала продолжается, есть ли еще шанс потерять записи в MongoDB?

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

Это из "Управление журналом" , что указывает на то, что вы можете потерять записи, сделанные с момента последнего сброса журнала на диск.

Если мне нужна более долговечность, "Чтобы заставить mongod чаще фиксировать журнал, вы можете указать j: true. Когда операция записи с j: true ожидает, mongod уменьшит значение journalCommitInterval до трети заданного значения."

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

Ответ 1

Опубликуйте новый ответ, чтобы очистить его. Я выполнил тесты и снова прочитал исходный код, и я уверен, что раздражение исходит из неудачного предложения в документации для записи о проблемах. При включенном журналировании и j:true проблемах с записью запись длительная, и нет никакого загадочного окна для потери данных.

Даже если ведение журнала продолжается, есть ли еще шанс потерять записи в MongoDB?

Да, потому что долговечность также зависит от реакции отдельных операций.

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

Это из "Управление журналом", что указывает на то, что вы можете потерять записи, сделанные с момента последнего удаления журнала на диск.

Это правильно. Журнал сбрасывается отдельной веткой асинхронно, поэтому вы можете потерять все с момента последнего флеша.

Если мне нужна более долговечность, "Чтобы заставить mongod чаще фиксировать журнал, вы можете указать j:true. Когда операция записи с j:true находится на рассмотрении, mongod уменьшит journalCommitInterval до трети set value."

Это тоже меня раздражало. Вот что это значит:

Когда вы отправляете операцию записи с помощью j:true, она не запускает сразу флеш-диск, а не сетевой поток. Это имеет смысл, потому что могут быть десятки приложений, говорящих с одним и тем же экземпляром mongod. Если каждое приложение должно было использовать много журналов, db будет очень медленным, потому что он все время синхронизирует.

Вместо этого происходит то, что "поток долговечности" будет принимать все ожидающие записи журнала и вывести их на диск. Поток реализован следующим образом (комментарии мои):

sleepmillis(oneThird); //dur.cpp, line 801
for( unsigned i = 1; i <= 2; i++ ) {
  // break, if any j:true write is pending
  if( commitJob._notify.nWaiting() )
    break;
  // or the number of bytes is greater than some threshold
  if( commitJob.bytes() > UncommittedBytesLimit / 2  )
    break;
  // otherwise, sleep another third
  sleepmillis(oneThird);
}

// fsync all pending writes                                      
durThreadGroupCommit();

Таким образом, ожидающая операция j:true приведет к фиксации потока фиксации журнала раньше, чем обычно, и будет фиксировать все ожидающие записи в журнале, в том числе те, которые не имеют j:true.

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

Команда write (или getLastError) с журналируемой проблемой записи j:true будет ждать окончания продолжительности синхронизации, поэтому нет риска потери данных (насколько это возможно для ОС и оборудования).

Предложение "Тем не менее, существует окно между фиксацией журнала, когда операция записи не является полностью долговечной", вероятно, относится к mongod, запущенному с включенным журналированием, который принимает запись, в которой NOT используется j:true беспокоиться. В этом случае существует вероятность того, что запись будет потеряна с момента последнего фиксации журнала.

Я написал для этого отчет об ошибках docs.

Ответ 2

Может быть. Да, он ожидает, что данные будут записаны, но, согласно документам, 'есть окно между фиксацией журнала, когда операция записи не является полностью долговечной ", что бы это ни было. Я не мог понять, на что они ссылаются.

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


Это немного сложно, потому что есть много рычагов, которые вы можете вытащить:

Настройки MongoDB

Предполагая, что ведение журнала активировано (по умолчанию для 64 бит), журнал будет фиксироваться через регулярные промежутки времени. Значение по умолчанию для journalCommitInterval составляет 100 мс, если журнал и файлы данных находятся на одном блочном устройстве, или 30 мс, если они нет (поэтому предпочтительнее иметь журнал на отдельном диске).

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

Заявление о контенте

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

Итак, в лучшем случае, есть 2 мс окна, где данные могут потеряться. Однако этого недостаточно для ряда приложений.

Команда fsync заставляет флеш-диск всех файлов данных, но это лишнее, если вы используете журналирование и неэффективно.

Долговечность

Даже если вы должны записывать каждую запись, что хорошо, если у администратора центра обработки данных плохой день и использует бензопилу на вашем оборудовании, или аппаратное обеспечение просто распадается?

Резервированное хранилище, а не на уровне блочного устройства, например RAID, но на гораздо более высоком уровне, является лучшим вариантом для многих сценариев: Имейте данные в разных местах или, по крайней мере, на разных компьютерах, используя набор реплик и используйте w:majority беспокоиться о том, что ведение журнала включено (журналирование будет применяться только к первичному, хотя), Используйте RAID на отдельных машинах, чтобы увеличить вашу удачу.

Это обеспечивает наилучшую комбинацию производительности, долговечности и согласованности. Кроме того, он позволяет настраивать проблему записи для каждой записи и иметь хорошую доступность. Если данные будут поставлены в очередь для следующего fsync на трех разных машинах, он может по-прежнему составлять 30 мс для следующего фиксации журнала на любом из компьютеров (в худшем случае), но вероятность того, что три машины опустится в течение 30 мс интервала, вероятно, в миллион раз ниже, чем сценарий, связанный с цепью-массовым убийством.

Доказательства

TL; DR: Я считаю, что мой ответ выше.

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

В write_concern.cpp мы находим (отредактированный для краткости):

if ( cmdObj["j"].trueValue() ) {
    if( !getDur().awaitCommit() ) {
        // --journal is off
        result->append("jnote", "journaling not enabled on this server");
    } // ...
}
else if ( cmdObj["fsync"].trueValue() ) {
    if( !getDur().awaitCommit() ) {
        // if get here, not running with --journal
        log() << "fsync from getlasterror" << endl;
        result->append( "fsyncFiles" , MemoryMappedFile::flushAll( true ) );
    }

Обратите внимание на вызов MemoryMappedFile::flushAll( true ), если установлен fsync. Этот вызов явно не входит в первую ветвь. В противном случае долговечность обрабатывается в отдельной ветке (соответствующие файлы с префиксом dur_). Забастовкa >

Это объясняет, для чего относится wtimeout: он относится к ожиданию ведомых устройств и не имеет ничего общего с I/O или fsync на сервере.

Ответ 3

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

Существует опция j:1, которую вы можете прочитать здесь здесь, которая гарантирует, что конкретная операция записи ожидает подтверждения до тех пор, пока она не будет записанный в файл журнала на диске (так не только на карте памяти). Однако это docs говорит об обратном.:) Я бы проголосовал за первый случай, и мне стало комфортно.

Если вы запускаете много команд с таким вариантом, mongodb будет адаптировать размер интервала фиксации журнала для ускорения работы, вы можете прочитать об этом здесь: DOCS этот, который вы также упоминали, а другие уже сказали, что вы можете указать интервал между 2-300 м.

Долговечность гораздо более обеспечена, на мой взгляд, по сравнению с параметром w: 2, а если операция обновления/записи подтверждается двумя членами в реплик-наборе, то на самом деле она вряд ли проиграет в течение одной минуты (интервал очистки файла данных), но не возможно.

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

Ответ 4

Я бы согласился с Sammaye, что journalwaling имеет мало общего с долговечностью. Однако, если вы хотите получить ответ на то, можете ли вы действительно доверять mongodb для сохранения ваших данных с хорошей согласованностью, я бы предложил вам прочитать этот сообщение в блоге. Существует ответ от 10gen относительно этого сообщения и ответ автора на сообщение 10gen. Я бы посоветовал вам прочитать это, чтобы принять обоснованное решение. Мне потребовалось некоторое время, чтобы понять все подробности самостоятельно, но этот пост содержит основы.

Ответ на сообщение в блоге был предоставлен здесь 10gen, компанией, которая делает mongodb.

И ответ на ответ был предоставлен профессором в этом сообщении.

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

Ответ 5

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

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