Заменил PostgreSQL на Mongo и сэкономил кучу денег

Ник Мэнинг — автор стартапа под названием Shindig. Это сервис, который помогает алкоголикам открывать для себя новые напитки и потом делиться впечатлениями с другими забулдыгами. Свой сервис Ник изначально основывал на активном использовании Линукса и свободных программ. Но по мере роста популярности сервиса разработчик стал замечать, что не все свободные программы одинаково выгодны в использовании.

Что было в начале

В качестве платформы для разработки Ник выбрал популярный web-фрэймворк Ruby on Rails. Контент было решено хранить в СУБД PostgreSQL. Все ПО досталось бесплатно, но за хостинг надо платить. Проанализировав производительность своего приложения на RoR/PostgreSQL и сопоставив ее со средним количеством посещений был выбран тарифный план за 100 долларов в месяц. Его почти сразу же стало не хватать и эксперты посоветовали Нику без промедления начинать искать дополнительные количества хрустящих зеленых купюр.

Как стало

Лишних денег у Ника не оказалось. На посетителях алкосервиса много не заработаешь, поэтому было решено снижать затраты с помощью изменения программной архитектуры приложения.

Тормозной фреймворк оставался прежним — чтобы не переписывать всю кодовую базу. PostgreSQL заменили на модную NoSQL-СУБД MongoDB, которой недавно так восторгался главный редактор Либератума. Часть запросов к базе данных выделили в отдельный сегмент и разместили в хранилище типа «ключ-значение» Redis. Поиск по сайту был полностью переделан с использованием ElasticSearch — высокопроизводительного поискового движка.

Когда все мероприятия были завершены, Ник стал с нетерпением ждать первых сводок о производительности. Задачей минимум было увеличение максимального количества одновременных посетителей сайта в несколько раз при сохранении действующего тарифа в 100 долларов. Задачей максимум — рост количества пользователей online при переходе на более дешевый тариф. Стоит ли говорить, что Ник был немало удивлен, когда получил от провайдера счет уже на 350 долларов за месяц обслуживания.

На чем остановились в итоге

С одним из главных виновников падения производительности — Ruby on Rails — было решено попрощаться. В качестве языка программирования был оставлен Ruby. Взаимодействие приложения с web-сервером перевели на интерфейс Rack.

Основным изменением стал отказ от MongoDB в пользу графовой базы данных Neo4j. Ориентированность на представление данных в виде графа идеально подходит для работы социальных сервисов, коим Shindig по сути и являлся.

Некоторые модули на Ruby были переписаны на относительно молодом языке программирования Go от Google. Go ориентирован на разработку многопоточных приложений, что пришлось очень кстати, учитывая большое число одновременных подключений к сервису.

Через месяц эксплуатации Ник получил счет всего на 60 долларов. И это при том, что аудитория выросла в разы.

Анализ ошибок, принятие решений

Сначала следует сказать, что всё используемое ПО очень хорошего качества и прекрасно подходит для использования в своих целях. Но есть области, где эти программы лучше не задействовать. Одна из таких областей — создание высоко посещаемого сайта со структурой социальной сети. Если вы создаете проект подобного класса, эти советы для вас:

Не используйте PostgreSQL

PostgreSQL является очень медленной базой данных и плохо подходит для хранения социальных данных и связей. Реляционная природа этой СУБД заставляла разбивать данные на множество таблиц. Извлекались данные с помощью запросов с большим количеством медленных операций объединения Left Join, что в процессе роста нагрузок привело к тяжелым последствиям.

Не используйте MongoDB

MongoDB — прекраснейшая СУБД. Она обладает удивительной гибкостью, легко интегрируется в Ruby on Rails и очень быстра на операциях чтения из одной коллекции. Но есть и недостатки, из-за которых MongoDB не подходит для построения социальных сетей: когда пользователи стали оставлять все больше разных типов контента, Ник стал замечать, что генерация ленты активности пользователей стала катастрофически замедляться. MongoDB очень плохо давались операции вида «выбрать все статьи, которые лайкнули пользователи из моего списка друзей». Нереляционный характер Mongo стал мешать.

По этой же причине от Mongo отказались разработчики свободной социальной сети Diaspora. История этого эпического фэйла подробно описана в статье «Why You Should Never Use MongoDB» («Почему ты никогда не должен использовать MongoDB»). Прим. главреда Либератума).

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

Используйте Neo4j

Когда нужно хранить в базе данных социальный граф — используйте специализированные СУБД. Переход на свободную графовую базу Neo4j моментально решил все проблемы с производительностью. Приятным бонусом стало значительное упрощение архитектуры приложения, ведь пропала необходимость использовать Redis для кэширования и ElasticSearch для индексации и поиска.

field_vote: 
Ваша оценка: Нет Средняя: 5 (1 оценка)
Названия программ: 
Программное обеспечение: 
Языки программирования: 

Комментарии

1. Одна из самых больших проблем MongoDB – это блокировки и гранулярность блокировок.
Сюда же, к блокировке относится — блокировки с миграцией чанков (англ. chunk). Когда задействован кластер, шарды и все такое. Вкратце расскажу про процесс миграции чанков. Когда надо перенести часть данных на какой-то новый шард, выбирать этот новый шард (наименее загруженный по умолчанию), данные туда копируются, происходит передача прав этому новому шарду путем записи в файл конфигурации сервера, и данные удаляются со старого шарда.

2. В настоящее время MongoDB может использовать только один индекс при исполнении запросов, даже если всего этих индексов несколько. Соответственно, это отметает всякие продвинутые оптимизации вроде слияния индексов (англ. index merge). При этом индекс не всегда угадывается правильно с точки зрения разработчика. Разработчик думает, что должен использовать один индекс, а используется другой. Почему? Потому что MongoDB выбирает этот план эмпирически.

3. Дальше идет объективный недостаток: нет распределения коллекций. Когда мы в кластере MongoDB создаем новую базу данных, она размещается на наименее загруженном шарде. Он считается домашним шардом. После этого все создаваемые коллекции будут размещаться на этом же домашнем шарде. Данные могут быть распределены на другие шарды только в том случае, если мы включим шардинг для коллекций.

Включать его для маленьких коллекций себе дороже, и лучше не стоит. Если у нас много небольших коллекций, то это может создать серьезные проблемы. Например, мы храним какие-то данные, логируем и группируем их по дням. Один день – одна коллекция. Для таких коллекций включать шардинг лучше не стоит, но и на одном шарде они все не поместятся. Для таких случаев советую либо не использовать кластер MongoDB и шардить все вручную, либо применять более традиционные средства.

И это только часть проблем, с этой СУБД;(

Оценка: 
Средняя: 5 (1 оценка)

Одна из самых больших проблем MongoDB – это блокировки

Да ну? Лет 5 назад может быть. Сейчас блокировка на уровне коллекции. И уже запилили блокировку на уровне документа. Документ в Mongo — это аналог строки в традиционной SQL-СУБД. Так вот, MyISAM в MySQL научился блокировать только на уровне всей таблицы. Монго уделывает всех.

В настоящее время MongoDB может использовать только один индекс

А что, составные индексы в Mongo уже Госдума запретила? ;)

Потому что MongoDB выбирает этот план эмпирически.

Как это эмпирически? Какой индекс заказал построить юзер — по тому и ищет. Но даже если что-то пошло не так, можно посмотреть логи профайлера, удалить ненужный индекс, построить нужный.

И это только часть проблем, с этой СУБД;(

Ну-ну. ;)

Оценка: 
Средняя: 5 (2 оценки)

Комментировать

Filtered HTML

  • Use [fn]...[/fn] (or <fn>...</fn>) to insert automatically numbered footnotes.
  • Доступны HTML теги: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote> <strike> <code> <h2> <h3> <h4> <h5> <del> <img>
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.