Почему не стоит использовать MongoDB (Сергей Туленцев)
Upcoming SlideShare
Loading in...5
×
 

Почему не стоит использовать MongoDB (Сергей Туленцев)

on

  • 4,238 views

 

Statistics

Views

Total Views
4,238
Views on SlideShare
2,904
Embed Views
1,334

Actions

Likes
2
Downloads
21
Comments
2

3 Embeds 1,334

http://www.highload.ru 838
http://archive.highload.ru 494
http://webcache.googleusercontent.com 2

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • ВMongoDB есть поддержка MapReduce. Это замечательный механизм обработки данных, много где применяется. В MongoDB он реализован на джаваскрипте, поэтому он очень медленный и однопоточный.Так, например, тривиальная обработка миллиона документов занимает на моем лэптопе примерно 23 секунды.Осталась у меня коллекция от какого-то прошлого эксперимента, я решил на ней попробовать MapReduce. Каждый документ содержит три поля: _id, булево значение и дату. Задача: подсчитать сколько раз встречается каждое булево значение в этой коллекции. С помощью MapReduceэто заняло 23 секунды. Простой запрос типа db.testcoll.count({bf : true}) занимает около 600-700 миллисекунд.
  • Memory Mapped Files – это механизм современных ОС. Как понятно из названия он устанавливает прямое соответствие между файлом и областью в памяти. После этого приложение может писать напрямую в память, а ОС позаботится о сбросе данных на диск. В большинстве случаев это увеличивает производительность (доступ к памяти на порядки быстрее системного вызова) и упрощает работу с большими файлами.Не обошлось, конечно, и без минусов. Так как управление берет на себя система, мы не можем контролировать, какие страницы находятся в памяти, а какие вытеснены на диск. Например, очень желательно, чтобы индексы находились в памяти. И вот кто-то не очень осторожный делает фулл скан большой коллекции, который поднимает её всю в память, вытесняя индексы. Из-за этого начинает тормозить все остальные запросы. Если не повезет, то система может и не прийти в прежнее состояние. Если бы мы управляли памятью сами, то мы могли бы лучше определять горячие места и знать, что держать в памяти. Еще один недостаток – это дыры в файлах. Предположим, что мы делаем удаления из коллекции. Как логично было бы предположить, физически объект не удаляется, а просто помечается как удаленный. Система почистит его при следующей ручной сборке мусора. Однако до этого он будет лежать на диске и занимать место. Итак, представим себе ситуацию, что мы равномерно удалили 80 процентов документов (к примеру). Допустим, раньше пять документов умещались на 1 страницу. Теперь, чтобы загрузить те же пять реальных документов, нам придется загружить 5 страниц. Это лишняя нагрузка на диск и расход памяти. В новой свежей версии MongoDB, которая вышла вот на днях, есть команда compact. Она позволяет сжать отдельную коллекцию (а не всю БД как раньше). Однако это по прежнему блокирует все остальные операции, так что лучше производить это на слейве.Еще один недостаток, напрямую не связанный с технологией MMF – это то, что MongoDBнельзя ограничить размер используемой памяти. Парни из Селектела утверждают, что она просто считывает размер памяти при старте и считает это своим лимитом. Это создает некоторые проблемы при использовании её в облачной среде, где доступная память на сервере может как расти, так и уменьшаться.
  • Одна из самых больших проблем с MongoDB – это гранулярность блокировок. В моем личном чарте это первое место. В MongoDBпринята модель «несколько читателей – один писатель». Писатель – один на сервер. Не на коллекцию, не на БД – на сервер! При этом писатель блокирует читателей. В версиях до 2.0 один неудачный апдейт клал систему. В этой версии они, вроде бы, научились ненадолго отпускать лок на запись при длительных операциях. Как это работает на деле, я еще не проверял. Но обещают.Сюда же относим блокировки при миграции чанков. Форум поддержки полон письмами про ситуации, когда миграция чанка встала. Да и мне лично эти проблемы стоили немалого количества нервов и волос на голове. Поясню вкратце, как происходит миграция. Выбирается новый шард. Данные копируются туда, происходит передача прав на чанк путем обновления конфиг серверов и данные удаляются со старого шарда. В версии 1.6 жутко тормозил этап удаления. Он мог спокойно выполняться и по три часа. Естественно, система в это время висела. Я задолбал всех разработчиков с этим и они что-то там подкрутили. Вышла версия 1.8 и в ней также продолжали вешаться миграции. В ходе разбирательств выяснилось, что всегда была виновата операция setShardVersion, которая вызывается несколько раз за время миграции. Иногда она отрабатывала быстро, иногда подвисала. Если подвисала, то надолго. Меньше 10 минут, кажется, не было ни разу. Соответственно, она берет write lock и все остальные операции ждут, а система стоит. Лечилось обычно перезапуском сервера, потому что ждать было некогда.
  • В настоящее время MongoDBпри выполнении запроса может использовать только один индекс. Никаких тебе оптимизаций вроде index merge. Причем конкретный план запроса выбирается опытным путем: запускаются все планы запросов одновременно и тот, который завершился первым, признается оптимальным и используется в дальшейшем. Время от времени этот процесс повторяется, потому что характеристики данных могли измениться и этот план уже не является оптимальным. Такая вот особенность, про которую неплохо бы знать.
  • ВMongoDB(как, впрочем, и во многих других системах) шарды равноправны. При добавлении нового шарда, данные равномерно рапределяются. Однажды, еще находясь под эйфорией и будучи излишне оптимистичен относительно сообразительности MongoDB, я решил добавить новый шард. Вот только он был в три раза меньше тех, что у меня уже были. Отчего-то я подумал, что монго перенесет на него данных соразмерно объему оперативной памяти. Что случилось, предсказать не трудно. Данные распределились равномерно и этот шард начал тормозить всю систему. Причем тормозил он её еще два дня, пока я с него данные выкачивал обратно. Ошибка тут, конечно, была моя, но, мне кажется, было бы неплохо уметь задавать шардам вес. Например, этот содержит Х данных. А этот 2Х. Потому что не всегда удается добыть идентичные машины.Далее идет объективный недостаток: нерасшарденные коллекции создаются всегда на первичном шарде. Например, у нас много не очень больших коллекций. Скажем, мы собираем какую-то статистику и группируем её по дням. Один день – одна коллекция. Так вот, все эти коллекции будут тесниться на первичном шарде, вместо того, чтобы создаваться на менее загруженном. На эту тему есть тикет. Обещали выпустить в 1.9. Теперь обещают в 2.1. Посмотрим. :-)
  • Ну, это просто. Для каждого приложения нужен мониторинг. Newrelic – это сервис, который позволяет узнать много нового про своё приложение. Он мониторит ваше приложение и собирает статистику по производительности, возникающие ошибки и прочее. В частности, позволяет смотреть, какие запросы к БД пользуются популярностью и какую нагрузку создают. Если, например, запрос длился слишком долго, то по нему можно посмотреть детали, вплоть до реальных команд, которые были отправлены в БД, с подставленными параметрами и планами запросов.Так вот, ничего этого для MongoDBнет, в силу её курсорной модели работы. Какие-то крупицы информации почерпнуть всё же можно, но на уровне «во время этого запроса был 3 раза вызван метод find для класса User». То есть, инструментируется конкретный маппер, а не работа с базой.Для тех кто привык уже к подобной отчетности, это может оказаться серьезным недостатком.

Почему не стоит использовать MongoDB (Сергей Туленцев) Почему не стоит использовать MongoDB (Сергей Туленцев) Presentation Transcript

  • Почему не MongoDB
    Сергей Туленцев
  • MapReduce
    Медленный
    Однопоточный
  • Map
    Читаем входную коллекцию (read lock)
    map для каждого документа (JS lock)
    Пишем во временную коллекцию (write lock)
  • Reduce
    Читаем временную коллекцию (read lock)
    reduce для каждого документа (JS lock)
  • Пост-обработка
    Пишем в выходную коллекцию (write lock)
  • Memory Mapped Files
    + управление памятью на системе
    - управление памятью на системе
    «Дыры» в файлах
  • Блокировки
    Глобальный write lock
    Write lock yielding (new)
  • Оптимизатор запросов
    Только один индекс
    Эмпирический
  • Шардинг
    Все шарды равноправны
    Нет распределения коллекций
  • Мониторинг
    Нет New Relic RPM
    Есть MMS
  • Спасибо!
    sergei.tulentsev@42bytes.ru
    @stulentsev