Особливості використання MongoDB


 
Трохи більше року тому мене попросили взяти участь у розвитку однієї відомої у вузьких колах (але не завжди з хорошого боку) соціальної мережі. У той час я вже був фанатом мови Haxe, тому з тим на чому писати питань не виникало. А от з БД вони з'явилися. Досвід використання MS SQL Server і MySQL говорили про те, що коли справа стосується великих обсягів інформації, то часом трапляються складності (практично неможливим стає зміна структури БД, а колись швидкі запити працюють вже критично повільно). Порадившись з колегами (у яких вже був досвід з Mongo), ми вирішили використовувати саме цю СУБД. А про ті особливості, які спливли протягом цього року я і розповім нижче.
 
 

Стабільність роботи

Через кілька місяців використання з'явилася цікава проблема. Справа була так: я запустив побудова індексу для однієї з колекцій, потім, виявивши, що індекс невірний, я дозволив собі зняти процес через db.killOp () . Після цього індекс формально з'явився, але при спробі використання БУДЬ-ЯКОГО індексу (за винятком natural ) в даній колекції СУБД повертала внутрішню помилку (спрацьовував якийсь assert в її коді). Т.к. колекція містила майже 100 млн. записів, то запити до неї стали неможливі і нам довелося на кілька днів зупинити сервіс, поки ми переносили дані в нову колекцію. А стара колекція так і живе у нашій базі — видалити її штатними засобами не виходить.
В результаті, зараз у нас всі колекції, які стосуються одному сервісу, кладуться в окремий instance СУБД, який у критичній ситуації можна зупинити і виправити, пожертвувавши доступність лише одного сервісу.
 
 

Запасні копії

Чимало часу було витрачено і на те, щоб вирішити, як виконувати резервне копіювання інформації. Перший приходить на розум спосіб — створення набору реплік — здався мало відповідним в тому сенсі, що часом потрібна не остання копія БД на момент збою, а більш рання. Крім того, при знятті бекапа, було б непогано не створювати додаткового навантаження на production. В результаті дійшли до використання master-slave конфігурації, при якій slave час від часу бекапе штатними засобами.
Хинт: щоб уникнути налаштування безпеки через сертифікати, можна просто створити користувача «repl» в БД local mater і slave інстанси:
 
 
use local
db.addUser("repl", "mypassword")

 
 

Унікальні індекси

Звикнувши до відносної безпеки SQL, можна потрапити в неприємності. У нас був такий казус: для однієї з колекцій ми запустили побудова унікального індексу по двох полях, одне з яких було відсутнє у великої кількості записів, а інше регулярно повторювалося. У результаті нашої помилки, СУБД почала видаляти дані з колекції. Вчасно зрозумівши це, ми зняли процес видалення по db.killOp () вже через кілька секунд, а інформацію пізніше відновили. Але осад, як кажуть, залишився. Тому, як написано в керівництві: використовуйте dropDups: true з обережністю!
 
 

Лічильники

Операції підрахунку кількості елементів, що підходять під заданий фільтр, на великих обсягах даних можуть виконуватися дуже довго, якщо порівнювати з SQL. Вся справа в тому, що Mongo не зберігає в деревах індексів кількість подсистемами. В результаті, навіть якщо ваш запит повністю підпадає під індекс, СУБД змушена обійти всі підходять під фільтр записи (адже часто їх немало). Так що будьте готові зберігати лічильники окремо і міняти їх коли потрібно. Або мати фонові сервіси, які будуть перераховувати значення лічильників з задане періодичністю. У нас використовуються обидва способи, залежно від ситуації (перший — в простих випадках, таких як кількість коментарів для картинки, а другий — для складних, коли потрібно зберігати кількість записів в колекції, що підпадають під різні набори умов).
 
 

Ротація логу

Не варто забувати про таку «дрібницю», як розмір log-файла. Адже по-замовчуванням Mongo пише в нього всі операції з базою. Тому на production-системі він може досить швидко з'їсти все місце на розділі. На некритичних інстанси (таких як призначений для бекапірованія slave), як мені здається, його краще взагалі відключати. На інших — організувати ротацію.
 
 

Безпека

Без спеціальної настройки може легко виявитися так, що Mongo буде дивитися в інтернет без пароля. Після первинної настройки, не забудьте створити користувача — адміністратора:
 
 
use admin
db.addUser("root", "mypassword")

 
Крім того, пам'ятайте, що у цієї СУБД в мережу може дивитися ще й http-сторінка (див. опцію nohttpinterface ) зі статистикою.
 
 

Повнотекстовий пошук

В цілому, він працює. Слід лише пам'ятати, що:
 
 
     
  1. мови (зокрема російська) підтримуються не зовсім коректно — Mongo, наприклад, користується низкою евристичних правил для детектування закінчень, але, судячи з усього, не зберігає списків виключень або чогось подібного, тому нічого особливо розумного від такого пошуку не чекайте;
  2.  
  3. якщо під пошуковий запит підпадає багато записів (ви шукали поширене слово) — буде погано; а саме: запити будуть виконуватися довго (в нашому випадку — порядку 30 секунд і більше) і на це важко якось вплинути без введення припущень (зробимо limit перед пошуком — не знайде частина даних — ну і добре).
    Тому, хоча ми і використовуємо повнотекстовий пошук в Mongo, але тільки тому що він йде «з коробки». Якщо якісний пошук критичний — використовуйте щось на зразок sphinx.
  4.  
 
 

Висновки

В цілому, я залишився задоволений нашим вибором: горизонтальна масштабованість і гнучкість документ-орієнтованої моделі переважують недоліки.
Зараз наша соціальна мережа функціонує на декількох десятках серверів, при тому, що зроблені нашою командою сервіси відмінно тримаються на одній машині для серверного коду (сам код написаний на мові haxe з використанням веб-фреймворку HaQuery і скомпільований в neko ), двох машинах для production-БД і однієї для slave-інстанси Mongo.
 
Сподіваюся, якщо ви роздумуєте використовувати MongoDB для свого проекту, ця стаття допоможе вам прийняти вірне рішення.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.