Гарантирует ли журналирование MongoDB долговечность?
Даже если ведение журнала включено, есть ли шанс потерять записи в MongoDB?
"По умолчанию наибольшее количество потерянных записей, т. Е. Не сделанных в журнал, - это те, которые были сделаны за последние 100 миллисекунд".
Это из Manage Journaling, которая указывает, что вы можете потерять записи, сделанные с момента последней записи журнала на диск.
Если я хочу большей долговечности: "Чтобы заставить mongod чаще фиксировать журнал, вы можете указать j: true. Когда ожидается операция записи с j: true, mongod уменьшит journalCommitInterval до трети установленного значения".
Даже в этом случае создается впечатление, что запись журнала на диск выполняется асинхронно, поэтому существует вероятность потери записи. Я что-то упускаю о том, как гарантировать, что записи не будут потеряны?
5 ответов
Отправка нового ответа, чтобы очистить это. Я выполнил тесты и снова прочитал исходный код, и я уверен, что раздражение исходит от неудачного предложения в документации по написанию. С включенным ведением журнала и j:true
Забота о записи, запись долговечна, и нет таинственного окна для потери данных.
Даже если ведение журнала включено, есть ли шанс потерять записи в MongoDB?
Да, потому что долговечность также зависит от отдельных операций записи беспокойства.
"По умолчанию наибольшее количество потерянных записей, т. Е. Не сделанных в журнал, - это те, которые были сделаны за последние 100 миллисекунд".
Это из Manage Journaling, которая указывает, что вы можете потерять записи, сделанные с момента последней записи журнала на диск.
Это правильно. Журнал очищается отдельным потоком асинхронно, так что вы можете потерять все, начиная с последней очистки.
Если я хочу большей долговечности: "Чтобы заставить mongod чаще фиксировать журнал, вы можете указать
j:true
, Когда операция записи сj:true
в ожидании, Mongod уменьшитjournalCommitInterval
до трети установленного значения."
Это тоже меня раздражало. Вот что это значит:
Когда вы отправляете операцию записи с j:true
, он не запускает очистку диска сразу, а не в сетевом потоке. Это имеет смысл, потому что могут быть десятки приложений, говорящих с одним экземпляром mongod. Если бы каждое приложение часто использовало журналирование, база данных была бы очень медленной, потому что она постоянно синхронизировалась.
Вместо этого происходит то, что "поток долговечности" будет принимать все ожидающие фиксации журнала и записывать их на диск. Тема реализована так (комментарии мои):
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
задавать.
Даже в этом случае создается впечатление, что запись журнала на диск выполняется асинхронно, поэтому существует вероятность потери записи. Я что-то упускаю о том, как гарантировать, что записи не будут потеряны?
Пишу (или getLastError
команда) с j:true
Журналированная задача записи будет ожидать завершения синхронизации потока долговечности, поэтому нет риска потери данных (если это гарантируют ОС и оборудование).
Предложение "Тем не менее, существует окно между фиксациями журнала, когда операция записи не является полностью долговременной", вероятно, относится к mongod, работающему с включенным ведением журнала, который принимает запись, которая НЕ использует j:true
напишите озабоченность. В этом случае существует вероятность того, что запись будет потеряна с момента последней фиксации журнала.
Я подал отчет об ошибке в документации для этого.
Может быть. Да, он ожидает записи данных, но, согласно документам, существует " окно между фиксациями журнала, когда операция записи не полностью долговечна", что бы это ни было. Я не мог выяснить, к чему они относятся.
Я оставляю отредактированный ответ здесь, но я перевернул себя назад и вперед, так что это немного раздражает:
Это немного сложно, потому что есть много рычагов, которые вы можете нажать:
Ваша установка 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_
).
Это объясняет, что wtimeout
предназначен для: он относится ко времени ожидания подчиненных устройств и не имеет ничего общего с вводом-выводом или fsync на сервере.
Журналирование предназначено для поддержания данных о конкретном mongod в согласованном состоянии, даже в случае безумия бензопилой, однако с настройками клиента через writeconcern это может быть использовано для снижения долговечности. Об этом пишут концерн DOCS.
Есть вариант, j:1
, о котором вы можете прочитать здесь, который гарантирует, что конкретная операция записи ожидает подтверждения, пока она не будет записана в файл журнала на диске (а не только в карте памяти). Однако это документы говорит об обратном.:) Я бы проголосовал за первый случай, он заставляет меня чувствовать себя более комфортно.
Если вы запускаете много команд с такой опцией, mongodb адаптирует размер интервала фиксации журнала, чтобы ускорить процесс, вы можете прочитать об этом здесь: DOCS, эту, которую вы также упомянули, и, как уже говорили другие, вы можете указать интервал между 2-300 мс.
На мой взгляд, надежность гораздо более надежна, чем опция w:2, в то время как если операция обновления / записи подтверждается двумя членами в репликационном наборе, то вряд ли они потеряют оба в одну минуту (интервал очистки файла данных), но не невозможны.
Использование обоих параметров приведет к тому, что, когда операция будет подтверждена кластером базы данных, она будет находиться в памяти в двух разных блоках, и на одном она также будет находиться в согласованном восстанавливаемом диске.
Я должен согласиться с Саммайе, что журналирование мало связано с долговечностью. Однако, если вы хотите получить ответ на вопрос, действительно ли вы можете доверять mongodb для хранения ваших данных с хорошей согласованностью, то я бы посоветовал вам прочитать этот пост в блоге. На этот пост есть ответ от 10gen и ответ от автора на 10gen. Я хотел бы предложить вам прочитать это, чтобы принять обоснованное решение. Мне потребовалось некоторое время, чтобы разобраться во всех деталях самостоятельно, но в этом посте были рассмотрены основы.
Ответ на сообщение в блоге дал здесь 10gen, компания, которая делает mongodb.
И ответ на ответ дал профессор на этот пост.
Это многое объясняет о том, как Mongodb может защищать данные, как они на самом деле функционируют, а также о производительности, которая требуется, если вы добавляете дополнительные защитные блокировки. Я очень хочу сказать, что эти три статьи являются лучшими, и, безусловно, наиболее полными являются те, которые говорят о преимуществах и недостатках mongodb, если вы думаете, что он односторонний, посмотрите на комментарии, а также посмотрите то, что люди должны были сказать, потому что, если что-то получило ответ от компании, которая сделала программное обеспечение, то, должно быть, оно дало хотя бы некоторые хорошие замечания.
Обычно потерянные записи являются проблемой в каждой системе, где существует буферизация / кэширование / отложенная запись между временем выполнения системы и постоянным (энергонезависимым) хранилищем, даже на уровне ОС (например, кэширование с обратной записью). Таким образом, всегда есть шанс потерять записи, даже если ваш конкретный провайдер (MongoDB) предоставляет функциональность для обеспечения надежности транзакций, именно базовая ОС отвечает за окончательную запись данных, и даже в этом случае происходит кэширование на уровне устройства... И это только нижние уровни, что делает систему очень параллельной, распределенной и производительной только усугубляет ситуацию.
Короче говоря, здесь нет абсолютной долговечности, только практическая / возможная / надежная на долговечность, особенно с хранилищем NoSQL, таким как Mongo, которое изначально не предназначено для согласованности и долговечности.