Pull to refresh

Comments 62

UFO just landed and posted this here
Может быть медленные диски и долго индексы в память загружаются? (как версия)
Посмотрев на сегменты с помощью утилиты vmtouch, так можно понять в какой части файла был индекс. Потом можно после перезапуска базы с непрогретыми кэшами руками почитать те части файла, на которые указал vmtouch и посмотреть изменится ли поведение первого поиска.
Почему про MongoDB в основном два типа статей?
1. Как все круто и все бегите сюда.
2. Как все плохо и близко не подходите к MongoDB.

Лично мне было бы интересней читать статьи в стиле: «Если делать вот так бездумно, то будут такие-то проблемы. Вы лучше так не делайте, а делайте вот так и будет вам счастье».

Вон про MySQL тоже есть и негатив и позитив. Но самое главное, есть те самые статьи, которые говорят о том, как обойти подводные камни и сделать то, что хотелось правильным путем.
Ни в коем разе не хотел этой статьёй сказать «как все плохо и близко не подходите».
Когда на рынке появляется новая технология, которая при этом еще и активно раскручивается, то хочешь-не хочешь по началу люди начинают исполюзовать её везде, где только можно и где нельзя. Смысл этой статьи как раз в том, чтобы поделиться сложностями и своим видением на то, когда эту базу лучше использовать.
Применительно к первой проблеме описываемой автором:
Запускали монгу в полном фарше mongos + configserv + mongod. Хотя и без шардов, но все равно использовали весь стек. Все в трех ипостасиях. Приложение (php-fpm) конектилось на один из трех mongos. Как вариант можно еще воткнуть локалько на каждых сервер с приложением haproxy который будет конектиться к mongos. Описываемой проблемы подвисания конекта не возникало.
А вот с локами да, до третьей версии совсем беда. На бд размером 10-20 Гб испытывали постоянные подвисания.
Относительно первой проблемы:
У нас было так. Было 2 машины с монгой (3.x версия). Одна мастер, вторая слейв. В таком варианте при выключении мастера происходит затык и подвисание. Если я не ошибаюсь и правильно помню, то восстановление так и не происходило пока обратно бывшего мастера не втыкали.
Добавили в репликасет третью машину — арбитра. После этого переключения стали достаточно быстрыми, что бы их не замечать и подвисания прекратились.
Да на двух машинах отказоустойчивость тестировать смысла особо нет. Надо как минимум 3 машины для кворума, ну или любое нечетное число больше 3х.
Поднимем 5ть small машин — 3 под базы,

Тогда в вашем случае полюбому арбитр нужен. 3-1=2 — привет splitbrain.
Попробуйте сделать то же самое только в варианте 3 под базы +1 арбитр. Я думаю подвиса не должно быть. Если сделаете тесты, то результат интересен.
Ненене, всего в реплик сете должно быть четное количество машин (минимум 3). У меня в тесте — как раз 3 машины. То, что третья машина — арбитр или просто ещё один secondary — это уже не принципиально. Если мощностей достаточно и хочется более надежной реплизкации, то делаем его еще одной репликой, если мощностей мало — то только под арбитр. При голосовании их голоса равноценны.
четное количество машин (минимум 3)
Это как?
Дико извиняюсь. Конечно же опечатка.
Начало вашего комментария напомнило:
У нас было два Оптерона, 16 гигабайт оперативки, 2 гига под мемкеш, полвинчестера свободно и целое множество плагинов и модулей всех сортов и расцветок, а также Апач, MySQL и гигабайт чистого свопа. Не то чтобы это был необходимый набор для Друпала, но если начал писать на PHP, становится трудно остановиться. Единственное, что вызывало у меня опасение — это своп. Нет ничего более беспомощного, безответственного и испорченного, чем свопящийся сервер. Я знал, что рано или поздно мы перейдем и на эту дрянь.
ibash.org.ru/quote.php?id=16079
А в какой инфраструктуре смотрели? В Amazon/DigitalPcean/VPS или прям на железках?
У меня стабильно воспроизводится на Amazon-е для версии MongoDB 2.6.x (3ку не смотрел).
Кстати, а как проверяли? Просто описанная траббла с подвисанием особенно актуальна для процессов-демонов, которые держат коннект постоянно.

Но казалось бы и фик с этой проблемой, в конце концов 45сек-1минуту даунтайма может и можно себе позволить в случае аварии, в конце концов сервера тоже не каждый день вылетают. Меня больше смущают эксепшены типа AutoReconnect, дубликаты и неоднозначное поведение python-драйвера
Больше всего по прочтении статьи волнует непостоянность автора в использовании изобретённого им правописания числительных (даже в одном предложении: «как при 15ти процессах-обработчиках, так и при 30»). Неправильно записаны «5 000 000онов», «MySQL 5ть.5ть», «vCPU 8ight, 15teen Gb RAM» и, конечно же, «2ва» и «3ри».
За что человека минусуют?
Абсолютно верно написал, тяжко читать такие цифры, а главное зачем?
Неужели вокруг на столько тупые люди, что «от 1 до 30» не могут прочитать и автору зачем-то пришло в голову писать «от 1го до 30ти»?
Просто во круг достаточно умные люди, что бы не обращать внимания в технической статье на такую херню как написание числительных. Тем более, что все понятно.
Понятно-то понятно, но читать штуки вроде «от 10есяти до 15ятнадцати» — несколько раздражает, согласитесь.
Удивляет «15ть» — 15 же и так читается как «пятнадцать», к чему там дописывать «ть»?
Не соглашусь.
Я в технических статьях в первую очередь смотрю на суть.
И я благодарен человеку, потратившему свое время, чтобы рассказать о своем полезном опыте.

P.S. Раздражать это может только учителей Русского языка, которым не важно что написано, а важно как.
Вы «русский» специально с большой буквы написали?

«Извозчик довезёт», всё как обычно.
Если статья техническая, то это не подразумевает что она может быть написана как угодно, всё-таки это публичный ресурс.
Выглядит как элементарное неуважение к читателю, ИМХО.
PS: Статья хорошая, тут претензий нет.
Ага, «умные люди», попробуйте не ставить знаки препинания и начинать предложения со строчной, а потом доказывайте, что это «такая херня» и «всё понятно». Не понятно. За каждое «пятьть» цепляется глаз, и внимание переходит с предмета обсуждения на то, чтобы понять, что автор в данный символ ничего особенного не закладывал, просто малограмотен. Повторите ошибки много раз, и, вместо технических выводов, статья породит только желание разгадать, по каким (неочевидным) законам ставится или не ставится костыль к цифре.

Пользоваться более чем пятью тысячами ста двадцатью девятью формами числительных в своих текстах, насколько я знаю, никто не запрещал. Более того, это предпочтительный вариант, если число само по себе не является центральным предметом интереса. Если оно важно, то можно записать его цифрой для удобства выделения из текста и сопоставления с другими. «На 3 потоках падение производительности практически незаметно: <результат теста>, но уже на 10 всё гораздо хуже: <результат теста>, из чего мы можем сделать вывод, что рост нагрузки нелинеен и при 100 потоках пользоваться системой будет невозможно». Я не верю, что есть человек, который способен тут прочесть «на три потоках», «на десять всё гораздо хуже», «при сто потоках». Следовательно, к украшательствам, да ещё и заново изобретённым без оглядки на существующие правила, можно 0тН0сиЦЦа соответственно.
UFO just landed and posted this here
Во всех графиках я не увидел очень важного параметра — общее затраченное время, может быть монга отрабатывает весь тест в 10х раз быстрее, пытаясь выполнить все задачи одновременно, что вызывает торможение на каждой операции. Когда Mysql (за счет транзакции) выполняет операции последовательно, тем самым давая хорошее время для единичной операции, но большее время в итоге.

Операция обновления большого кол-ва документов — не частая задача, чаще происходит обновление по одному документу (типичное обновление), поэтому больший смысл был бы тестировать именно его.
Про общее затраченное время — в случае MySQL оно составляет в районе 18ти секунд на один проход количеством N (1..30) процессов по всем юзерам и практически не меняется при нарастани числа воркеров. В случае MongoDB оно составляет в районе 40секунд:
вывод консоли тут
(mongodb-performance-tests)[foo@ip-10-0-0-158 tool]$ python run_test.py --adapter mongodb --name mongodb_3_0_wt
Running «mongodb_3_0_wt» test
Prepare database

Create user documents
Full time: 97.6963868141
OK! Users were created!

Run test with 1 proceses
Test is finished! Save results

Full time: 145.417565107

Run test with 2 proceses
Test is finished! Save results

Full time: 72.3193061352

Run test with 3 proceses
Test is finished! Save results

Full time: 56.4604640007

Run test with 4 proceses
Test is finished! Save results

Full time: 43.2622559071

Run test with 5 proceses
Test is finished! Save results

Full time: 38.1150348186



Run test with 10 proceses
Test is finished! Save results

Full time: 40.7822709084

Run test with 11 proceses
Test is finished! Save results

Full time: 39.3015518188

Run test with 12 proceses
Test is finished! Save results

Full time: 37.2085850239

Run test with 13 proceses
Test is finished! Save results

Full time: 42.0286569595

Run test with 14 proceses
Test is finished! Save results

Full time: 40.7457239628

Run test with 15 proceses
Test is finished! Save results

Full time: 45.9798600674



Run test with 20 proceses
Test is finished! Save results

Full time: 44.4311590195

Run test with 21 proceses
Test is finished! Save results

Full time: 46.1173479557



Run test with 25 proceses
Test is finished! Save results

Full time: 43.7823390961



Run test with 29 proceses
Test is finished! Save results

Full time: 42.1524219513

Run test with 30 proceses
Test is finished! Save results

Full time: 43.6515491009

Finish!


По поводу обновления большого количества документов — ну вот не факт. Например, если ваша структура данных аля древовидная (каталоги, подкаталоги, подподкаталоги и т.п.), то без массовых обновлений не обойтись
Вы, между тем, забыли главное — в случае отвала мастера монга секунд 15 потупит и нового выберет сама, а тот же мускуль — нет.
Попробуйте, кстати, запустить тест с pymongo 3.0 — они там обещали накрутить много ништяков в плане мониторинга репликасета.
Не могу сказать насчет репликасета, но сама монга с третьей версии стала гораздо быстрее. В реальном проекте на процентов тридцать(!).
Но нужно использовать их новый «движок».
Не только быстрее, но и меньше места жрет за счет сжатия. Когда я проверял — в разы меньше.
Дык я и не говорю, что «Монго — это зло, давайте дружно переходить на MySQL» :-)
Репликация и шардинг из коробки вообще как киллер фича монги, очень подкупают.
Про эти 15ть секунд, как я и писал выше в комментариях, тоже не так страшно.
Основная траббла, в подвисании воркеров, ошибках AutoReconnect и в том, что pymongo не знает, удалось ли ему создать документ или не удалось. А самому руками генерить ObjectId в коде на каждый insert — далеко нетривиальная штука.
Не очень понял про запись. Поставьте write concern нужный и все. Там, конечно, есть свои подводные камни, но нормальным людям достаточно :)
Вы не совсем меня поняли, да и наверное я объяснил не совсем правильно. Все почему-то набросились на 15ть секунд таймаута, хотя это тут вообще дело 10ое.

Основная проблема в эксепшенах типа AutoReconnect. Эти эксепшены происходят из-за проблем с сетью, не важно работаете ли вы на репликсете или шардированной конфигурации или же на одном сервере монги без ничего. Т.е. если драйвер pymongo в какой-то момент работы не получает ответ от сервера, то он райзит такой эксепшен. Один из частных случаев, как это воспроизвести — это отрубание primary в репликсете из 3х машин.

Проблема pymongo (и возможно MongoDB тоже) в том, что он не может проконтролировать, добавился ли документ в момент insert-а или же нет. Т.е. вы должны контролировать это сами в своем коде.
Почему эксепшен это проблема? Если вы его словили, то операция не выполнилась, и у вас есть выбор — попробовать еще раз или забить. Если вы пишете с определенным write concern, то база и драйвер вам более-менее гарантируют то, что после возвращения из функции записи данные попали на выбранное количество реплик. Если это не так — кидается эксепшен.
Почему эксепшен это проблема?

Потому что эксепшен в данном конкретном случае не гарантирует, что запись не прошла — она могла пройти, а погла не пройти. write concern здесь вообще не при чем
emptysqua.re/blog/save-the-monkey-reliably-writing-to-mongodb
jira.mongodb.org/browse/PYTHON-197
Вставлю свои 5 копеек. Может кто-то сталкивался и подскажет как решать вопрос.
Дано: mongodb cluster: 3 config server, 4 shard, каждый shard это реплика из 3х серверов + арбитр.
Шардирования на уровне коллекций нет. У нас много мелких баз и они равномерно размазаны по шардам.
Кластер приложения. Рядом с каждой нодой стоит router.

Баг 1.
Как воспроизвести точно не знаю. Но сценарий такой:
1. Создаём базу main (допустим она попала на sh 001)
2. Пишем туда что-нибудь
3. Удаляем базу (да. нам иногда надо снести базу полностью чтоб просто её пересоздать)
4. Создаём её опять (для примера, она попадает на sh 002)
И вот теперь проблема: роутер через который это делали, знает что база на sh 002. а остальные роутеры видимо хранят кэш и думают что база на sh 001. Последствия катастрофические: пишем документ — ок. тут же читаем — даже базы нету. Или два процесса пишут свои данные в разные базы main.

Баг 2.
Я считаю его практически блокером: отсутствие нормального бэкапа. Да, я читал все мануалы, да, я знаю про mms. Сделать консистентный бэкап — та ещё задача. Но я не придираюсь. Я готов и на «хоть какой-нибудь бэкап кое-как».
Сценарий:
1. Для бэкапа максимально одновременно я блокирую по одному слэйву из каждого шарда на запись.
2. Делаю mongodump (отрабатывает успешно) со всех шардов.
Восстановление: делаю mongorestore — в 70% я получаю duplicate error при попытке построить индекс в конце восстановления. Пробовал и с oplog, и без. Кстати, индекс применяется ДО того как oplog накатывается. Возможно, этот oplog и исправил бы проблему.
Вывод: бэкап вы сделаете. А вот восстановить — как повезёт.
Тут есть ещё разные варианты: я тестировал бэкап через LVM + тянуть прямо с файлов, а не из процесса. Работает стабильнее. Вероятно придётся перейти на этот способ.

Баг 3.
Мутный баг. Иногда просто нельзя удалить коллекцию или базу. Помогает рестарт роутеров.

И это я только с позиции админа. С позицию девелопера я лучше промолчу.

По поводу бага 2 — вы какую версию mongo используете (с которой дамп снимаете)? случаем не 2.4? а в какую версию восстанавливаете — 2.6-3.0?
Просто интерсный баг был в версии 2.4. Вот например есть у нас коллекция со следующей структурой:

>db.entites.findOne()
{
        "_id" : ObjectId("54837b27bf0a898b0cbb3b78"),
        "path" : "/home/foo/bar/",
        "owner_id" : 42,
        "some_value_1" : 1,
        "some_value_2" : 2,
        "some_value_3" : 3
}

>db.entites.ensureIndex({"path": 1, “owner_id”: 1})


Т.е. поле path — хранит путь — строку произвольной длины. И вот, допустим, пользователь создает документ, где поле path длиной более 1024 символов:

>db.entites.insert({path: new Array(1025).join('x'), owner_id: 42, "some_value_1" : 1, "some_value_2" : 2, "some_value_3" : 3})


И все. Документ пропал. Выполняя запрос:

>db.entites.find({path: new Array(1025).join('x'), owner_id: 42}).count()
0

вы его не найдете. А все потому-то:
http://docs.mongodb.org/manual/reference/limits/#Index-Key-Limit
The total size of an index entry, which can include structural overhead depending on the BSON type, must be less than 1024 bytes.

То есть монга 2.4 разрешает документ создать, но не добавляет его в индекс, потому что поле path больше максимально возможной длины.
Кстати вот такой запрос-таки найдет пропавший документ:

>db.entites.find({path: new Array(1025).join('x'), owner_id: 42}).hint({_id: 1}).pretty()


А вот монга 2.6 такой документ создавать не разрешает и на моменте insert-а кидает эксепшен:

> db.entites.insert({path: new Array(1025).join('x'), owner_id: 42, "some_value_1" : 1, "some_value_2" : 2, "some_value_3" : 3})
WriteResult({
        "nInserted" : 0,
        "writeError" : {
                "code" : 17280,
                "errmsg" : "insertDocument :: caused by :: 17280 Btree::insert: key too large to index, failing test.entites.$path_1_owner_id_1 1037 { : \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...\" }"
        }
})


В любом случае, я бы посоветовал бы вам делать mongorestore c ключиками --drop (чтобы на всякий пожарный удалить существующую коллекцию если она есть) и --noIndexRestore (чтобы при восстановлении восстановить без индексов, а потом их нагнать руками)
Монгу используем 2.6.6
Восстанавливаю всегда в пустую базу.
noIndexRestore + потом руками — в чём смысл? А если я не знаю какие индексы надо создавать. Ковыряться в дампе и искать их?
А что насчёт автоматизации? Мне надо автоматически раскидывать дампы на разные окружения. И я не могу сделать нормальный restore.

А как же 3 вида админов: кто не делает бэкапы, кто делает и тот кто проверяет :)
не, ну я к тому, что для начала надо понять почему нельзя сделать нормальный ресторе. Т.е. локализовать проблему — т.е. это проблема утилиты mongorestore или проблема схемы данных или проблема что дамп при помощи утилиты mongodump делается как-то неправильно. Т.е. один раз руками расковырять, разобраться, решить проблему, а потом автоматизация и пр.
Легко на словах. А на деле не так просто понять.
Вот я залочил базу (слэйв).
Я сделал mongodump. Результат — ок. Ошибок не было. Команда успешно завершена.
Как мне определить, что mongodump отработал не верно?
Делаю restore — ошибка. Плохие данные? Ошибка в restore?
А размер 45 GB дампа.

ПС. И это хорошо, что мы пока коллекции не шардируем. С таким ненадёжным бэкапом если оно упадёт, а все коллекции размазаны по всем базам, до кучи баги роутеров с кэшем, восстановить это будет нереально.

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

Да, я понимаю, что процесс не быстрый. Но как вариант решения — сгодится
query_cache_size = 1024M

Я бы не рекомендовал ставить такие большие значения. MySQL будет блокироваться при инвалидации кэша ощутимо дольше, чем при кэше в 128-256MB, что на практике может приводить к «затыкам».

haydenjames.io/mysql-query-cache-size-performance
ok! спасибо за совет — учтем.
В новой версии 3.0 создатели утверждают, что с переходом на альтернативный движок WiredTiger ситуация должна улучшиться, поскольку он использует блокировки на уровне документа, а не блокирует базу целиком, как было в движке MMAPv1.


В MMAPv1 блокировка на уровне коллекции, а не базы.
Да, точно. С 3.0 блокировка на уровне коллекций:
docs.mongodb.org/manual/release-notes/3.0/#mmapv1-concurrency-improvement
MMAPv1 Concurrency Improvement
In version 3.0, the MMAPv1 storage engine adds support for collection-level locking.

Как-то упустил это из виду. Видимо слишком увлекся релиз нотисами про WiredTiger.
Вообще-то ещё в марте вышла 3.0, где lock на уровне документа. И перейти на новый движок WiredTiger ничего не стоит. Так что статья не актуальна с момента публикации.
Мне кажется вы как-то поспешно делате выводы, не прочитав пункт про Global lock. Там говорится и про 3.0 и про WiredTiger в том числе
Не ясно зачем писать про global lock, который неактуален уже несколько лет, писать заголовком. А где-то в тексте дописать, мол да, не актуально уже. И даже collection lock не актуален, т.к. повторюсь, что смигрировать на WiredTiger можно очень быстро. Собрать плюсиков от толпы хейтеров?

п.с. статью, если что, прочитал полностью ;)
1. То что в Mongo 3.0 MMAP лок на уровне коллекции, а не на уровне базы — это не сильно спасает. А про WiredTiger в плане производительности говорить о каком-то прорыве еще рано. Да он в каких-то кейсах он быстрее MMAP, но реляционным БД продолжает проигрывать. Вот тут например пишут, что у WiredTiger медленный поиск по ключу, потому что он не может поместить индекс в память. Совсем не good.

2. Даже если проект делается с нуля — использовать ли WiredTiger или не использовать — это большой вопрос. WiredTiger — если что, еще даже не движок по умолчанию. Если посмотреть багтрекер 10gen, то в WiredTiger много всего интересного. Например, вот:
jira.mongodb.org/browse/SERVER-20204
или вот:
jira.mongodb.org/browse/SERVER-17456
Вы с такими багами пойдете в продакшен? я вот что-то сомневаюсь.

3.
смигрировать на WiredTiger можно очень быстро

Начнем с того, что данные надо мигрировать через backup-restore. Это процедура совсем не быстрая Вот у меня есть база 2.6 на 20млн нод активных данных с двумя шардами и репликацией. Запись идет постоянно, чтение тоже постоянно.
Вы думаете я рискну взять и обновить базу только потому что вышел новый движок? :-) Да даже если бы и не надо было делать backup-restore обновление продакшен базы с одной мажорной версии на другую черевато проблемами. А уж зная MongoDB и как ребята по стартаперски рубят обратную совместимость…
1. Ещё раз, DB Level Lock был пофикшен в MongoDB 2.2 ещё в далёком 2012 году.

2. WiredTiger пока не по умолчанию исключительно по одной причине: чтобы разработчики не боялись обновляться на 3-ю версию.

3. Да, вот так жестоко зарублена обратная совместимость, что даже новый, полностью совместимый движок, не включен по умолчанию.
1. Ещё раз, DB Level Lock был пофикшен в MongoDB 2.2 ещё в далёком 2012 году.
У меня складывается ощущение что вы не смотрели ссылку, которую сюда же сами и написали. Там написано «MongoDB 2.2 increases the server’s capacity for concurrent operations with the following improvements: DB Level Locking, Improved Yielding on Page Faults»
В MongoDB 2.2 global lock был переведен с уровня процесса mongod на уровень базы. Плюс добавили «приспускание» лока во время долгих операций (аля update/delete). Ни о каком фиксе и речи не идет. Он как был так до сих пор и есть. Просто сужают область — сначала был процесс mongod, потом сделали на уровне БД. В MongoDB 3.0 сделали на уровне коллекции.

WiredTiger пока не по умолчанию исключительно по одной причине: чтобы разработчики не боялись обновляться на 3-ю версию.
Сомневаюсь. Баги на багтрекере говорят об обратном

Да, вот так жестоко зарублена обратная совместимость, что даже новый, полностью совместимый движок, не включен по умолчанию.
Про проблемы обратной совместимости хотя бы между 2.4 и 2.6 я писал уже выше.
Недавно в WT был баг с silent data corruption при использовании zlib. Потом мы словили развал всей базы (kernel panic на операции записи на диск), что привело к невосстановимо поврежденной базе… Но это было на уровне 3.0.1-3.0.2, может сейчас ситуация получше ,)
Да, я дейтсвительно недопонял, что это только импрувмент, а не выпиливание. А выпили (заменили на collection-level locking для MMAPv1, и на document-level locking для WiredTiger) таки только в 3.0.
но реляционным БД продолжает проигрывать
Это зависит от задачи, можно наделать тестов где mysql будет проигрывать, например поиск в массивах, вычерпывание очереди, upsert, sparse, плавающие размеры данных и т.д.
Тут например монга обошла в 20-100 раз mysql.

Так же пару лет назад были популярные статьи как компании переходили с *sql на mongodb и получали х10 ускорение…

А то что у вас такие конские апдейты, возможно говорит о не продуманной архитектуре
Каждая задача — обновление булевого поля всех 5 000 документов пользователя.
В данном случае можно было просто обновить один документ пользователя и все.
Это зависит от задачи, можно наделать тестов где mysql будет проигрывать, например поиск в массивах, вычерпывание очереди, upsert, sparse, плавающие размеры данных и т.д.
Тут например монга обошла в 20-100 раз mysql.
Тесты тестам рознь. Если тестировать БД что называется «из коробки», то грош цена таким тестам. В той статье, что вы привели, помоему так и есть. Особенно судя по вот этому абзацу:
>Use case #1: Insertion of millions of records in parallel:

>The winner in this use case is MyISAM engine. MyISAM doesn’t neither support foreign key constraint nor transactions (unlike InnoDB). MyISAM index works good in insertion operation given that the record size will be changed, but it will be bad in case of delete/update operation.
То есть люди явно не настроили параметр innodb_flush_log_at_trx_commit в конфигах для InnoDB. Но казалось бы и пофик. Пусть даже этот тест правдив. Еще раз хочу сказать, цель данной статьи — не сказать, какая MongoDB плохая, а MySQL такой весь из себя хороший. Цель — поделиться мнением, когда MongoDB можно использовать, а когда могут возникнуть сложности.

А то что у вас такие конские апдейты, возможно говорит о не продуманной архитектуре
Конкретно в моем проекте такого количества апдейтов нет. Но тем не менее проблема с массовыми операциями есть — они выполняются не так быстро, как хотелось бы. Пример, который я привел в статье — это бэнчмарк.
А зачем ReadPreference.SECONDARY_PREFERRED, как оно вообще относится к отказо-устойчивам write?

По поводу проблем подвисания коннекта, я советую попробовать вместо остановки инстанса в вашем тест убить процесс монги — результат может удивить. Я не на 100% уверен, т.к. с питоновым драйвером почти не общался, но у меня есть такое ощущение, что проблема вечного коннекта и неполучения отлупа это либо специфика AWS сетевой инфраструктуры, либо косяк в питоновом драйвере.

А что касается многократной записи и дупликатов — в относительно свежих версиях java драйвера есть поддержка retry policy, которая как раз для этого придумана. Ну и очевидно, что и без всякой поддержки в драйвере это решается элементарно, созданием DBObject (или что там вместо него в питоне) вне цикла, и запись с одним и тем же _id не пройдет.

По поводу выбора нового мастера за минуту — ни разу такого не видел, обычно это вопрос 2-5 секунд.

> Если через 5ть секунд драйвер PyMongo не получает от базы никакого ответа, то он сбрасывает соединение и выплевывает ошибку. Не самое классное решение — вдруг база перенагружена или запрос очень тяжелый и выполняется более 5ти секунд

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

Я бы скорее назвал статью «особенности питонового драйвера монги в AWS инфраструктуре», чем такое желтоватое как сейчас.
>А зачем ReadPreference.SECONDARY_PREFERRED, как оно вообще относится к отказо-устойчивам write?

потому что read тоже зависает. чтобы он не зависал при гибели мастера нужно чтобы он читал с secondary

>По поводу проблем подвисания коннекта, я советую попробовать вместо остановки инстанса в вашем тест убить процесс монги — результат может удивить

зачем? мне интересна именно смерть инстанса а не смерть процесса. Смерть процесса это как раз-таки случай не такой частый

>Ну и очевидно, что и без всякой поддержки в драйвере это решается элементарно, созданием DBObject (или что там вместо него в питоне) вне цикла, и запись с одним и тем же _id не пройдет.

ну собственно в статье про это и написано. Только это совсем не элементарно и не интуитивно понятно. Да и выглядит как костыль костылем

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

нет, на коннект как раз-таки есть свой таймаут. он называется connectTimeoutMS: api.mongodb.org/python/current/api/pymongo/mongo_client.html#pymongo.mongo_client.MongoClient

> потому что read тоже зависает. чтобы он не зависал при гибели мастера нужно чтобы он читал с secondary

это какая-то мистика. ReadPreference.SECONDARY_PREFERRED не значит, что «если мастер недоступен, то читать с slave», но значит, что мы всегда позволяем читать с него. Единственное, чему это поможет в смысле высокой доступности, что чтение будет доступно пока не закончились выборы нового мастера.

> зачем? мне интересна именно смерть инстанса а не смерть процесса.

Затем, что если остановка инстанса не закрывает коннект (я такое читал на их форуме) по причинам/особенностям организации сетевого стека AWS, то это тогда не про «монго не поняла / работает не так», но коннект не сбросился на стороне амазона, что относится к монго ровно настолько, насколько оно относится к любому приложению работающему с сокетами.

> Только это совсем не элементарно и не интуитивно понятно

А какого волшебного поведения вы в этой ситуации ожидали? Что произойдет что именно? На фоне отсутствия транзакций, такое поведение как раз вполне ожидаемо. Если хочется транзакций — ну так либо сделайте их сами, либо принимайте то, что в монге их нет и обеспечение целостности данных это задача приложения.

и да, с практической точки зрения вам надо использовать heartbeat, где можно задать для пула и частоту, и таймаут и все прочее (в java driver это heartbeatConnectRetryFrequency и прочие heartbeatConnectTimeout). Тогда зависший коннект не подвесит весь мир.
>ReadPreference.SECONDARY_PREFERRED не значит, что «если мастер недоступен, то читать с slave», но значит, что мы всегда позволяем читать с него.

Ну таки да. Всегда читаем со слейв, и тем самым обходим проблему. Именно это я и имел ввиду.

>Затем, что если остановка инстанса не закрывает коннект (я такое читал на их форуме) по причинам/особенностям организации сетевого стека AWS,

Как то очень странно звучит. У других приложений такой проблемы не наблюдалось :-)

>А какого волшебного поведения вы в этой ситуации ожидали?

Ну как минимум, что будет гарантирован результат — удалось записать данные или не удалось. А не просто «ошибка, а дальше сам гадай, записалось оно или нет». Тут дело не в транзакциях. Тарнзакции это дело 10ое. В тех же самых РСУБД вы можете не использовать транзакции, и тем не менее они гарантируют результат записи.
Читал статью пока Mongo удалял чуть менее 100 тыс записей из коллекции без каких-либо условий.
В Postgres или mySQL я бы успел разве что глоток кофе сделать.
Sign up to leave a comment.

Articles