Наверх ▲

Распространенные ошибки применения баз данных

Сергей Аверин Сергей Аверин Руковожу разработкой проектов в Баду. Программирую server-side. Конференционный маньяк. Среди проектов, которые я делал — Хабрахабр, dirty.ru, trendclub.ru. Специализируюсь на больших/сложных веб-проектах.

twitter: twitter.com/ryba_xek
facebook: facebook.com/ryba.xek

 

Сергей Аверин: Здравствуйте! Меня зовут Сергей Аверин. Мой доклад посвящен больше архитектуре, чем базам данных. Другое название презентации: "Семь советов стартапам, или что нам стоит дом построить?"



Я работаю в компании "Badoo". Это крупная социальная сеть, которая в основном разрабатывает сайт знакомств. Она предназначена для людей, которым интересно познакомиться с другими людьми, которых они до этого не знали. Мы входим в Top-200 "Alexa" с 2007-го года. Также входим в "Google" Top-100 Sites и почему-то располагаемся выше "Одноклассников" и "Mail.ru". У нас порядка 149-ти миллионов зарегистрированных пользователей. Каждый день регистрируется 150 тысяч новых пользователей. Когда был "Facebook API" – доходило до миллиона.

Ежедневно пользователи загружают порядка 3-х миллионов фотографий. У нас действуют два больших дата-центра: один - в Европе, другой - в Америке. В каждом - примерно тысяча серверов. С точки зрения разработчика, показатели PHP backend, которые формируют сайт, достигают в пике до 30-ти с лишним тысяч динамических запросов в секунду.

Мы часто используем программное обеспечение, расположенное в открытом доступе. Мы также ведем собственные разработки. Основное – это PHP MySQL, PHP FPM, который был написан одним из сотрудников нашей компании, сервис статистики для PHP Pinba. Кроме того, мы самостоятельно модернизируем mem cache, "Linux" (на основе "Suse") и "JANIX".

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

В действительности это трата ресурсов без возможности получить быструю отдачу. Вы инвестируете деньги в землю. Еще не понятно, будут у вас высокие нагрузки или нет. Мне кажется, что в 99-ти случаях из ста их не будет. Самое главное – решить сложные вопросы архитектуры. Об этом зачастую не знают или забывают. Или (как чаще всего бывает) не хватает информации о рынке, продукте, клиентах, их нуждах.

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



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

Многое все равно придется переделывать. Поэтому, наверное, стоит начать с быстрых, простых и дешевых решений по рецепту.


Когда у вас появятся клиенты, появится и опыт работы. Вы поймете, в каком направлении стоит разрабатывать продукт и на какие нагрузки он будет расчитан. Прийдет понимание и в плане архитектуры.

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

Во-вторых, нельзя забывать об отказоустойчивости.

Что касается отказоустойчивости, на мой взгляд, молодые стартапы берут базы данных с "Full Acid", создают шикарный журнал, "write-ahead log", читают умные книги и утверждают: "Мы все спроектировали правильно. Все отказоустойчиво. Мы ото всего защищены". Но проблемы могут возникнуть, т.к. нижним уровням может уделиться недостаточно внимания.

Что именно я имею в виду? Какое оборудование используется и в каком стоит дата-центре, насколько надежен провайдер и велика ли роль человеческого фактора.

Расскажу историю, актуальную для "Badoo". Допустим, в вашем дата-центре выкуплено десять стоек. Пришел администратор из чужой компании и задел наши провода. В итоге сервис "лег". Вопрос года звучит следующим образом: "Что произойдет, если вдруг сгорит ваш дата-центр?"

Поэтому, пожалуйста, подумайте, какие у вас есть внешние риски (может быть, технологические).

Кому-то достаточно рисовать 503-ю страницу, если что-то сломалось. Он считает, что это нормально. Для большинства стартапов это так.

Для некоторых сервисов отказоустойчивость означает хотя бы минимальную обработку запроса (например, взятие информации из кеша). Или выдачу информации на основе использования прежних данных. Для других фирм отказоустойчивость означает полноценную работу во время сбоя в системе. Также можно данные из одного дата-центра или от пользователя отправить в другой дата-центр, чтобы динамический запрос был обработан.

Самый большой фактор, от которого страдал лично я – это взаимозависимость сбоев. Когда начинает "тормозить" база данных, а за ней – PHP, то все остальное (сеть, switch) тоже начинает создавать неудобства. Обычно так отключаются электростанции. Одна вышла из строя, а за ней через 15 минут все остальные. Как решить проблему – вообще непонятно. Если "поднимать" по одной, то она в конечном счете вернется в неработоспособное состояние.

Практика показала, что один сервер здесь ни при чем. Все дело в недостатках архитектуры. Нужно обязательно создавать ее таким образом, чтобы вы были готовы к физическому выходу из строя одного сервера.

Как это сделано в "Badoo" на примере данных о пользователях? Сразу предупреждаю, что эти данные составляют, наверное, половину всего объема хранимых данных.

В «Badoo» используются специальные БД-серверы проверенного вендера. Мы знаем их failer Raid. Для каждого сервера имеется два блока питания, есть резервирование питания. В ДЦ — дизель-генераторы. В сервере стоит Raid 1+0. Четыре SAS-диска, которые быстро, аккуратно и надежно восстанавливаются. Пожалуйста, не используйте Raid 5 для баз данных.


Следующий уровень – программное обеспечение "Linux" на основе "Suse Linux", с различными правами доступа для разных групп пользователей. Доступ в "MySQL" имеют, по большому счету, только администраторы. В самом "MySQL" пользователи и пароли для разных сервисов тоже отличаются. Стоит "Firewall". Вместо "MySQL" мы весьма выгодно используем Percon-сервер. Также "MySQL" находится в chroot-окружении, что повышает надежность работы.

Что касается архитектуры приложения, специфика пользовательских данных такова, что данные обязательно нужно писать в транзакции. Событие, которое она порождает, нужно тоже писать в транзакции на том же сервере. Поэтому изначально запись в транзакции действительно производится ровно и на один сервер.

Но у каждого сервера с пользовательскими данными есть "брат-близнец" в другом дата-центре, который дублирует данные. Это необходимо для создания резервных копий и более быстрого чтения. Очень быстро запускается скрипт, который отображает произведенные изменения. Новые данные переписывают в общую очередь, которая хранится на нескольких серверах на той же самой площадке. Затем информация переносится в другой дата-центр, где отдельные скрипты производят обновление копии.

В-третьих, стоит позаботиться о резервах БД. Могут ли два сервера выйти из строя одновременно? Это маловероятно. Конечно, нельзя полностью защититься от выгорания дата-центра дотла. В таком случае часть неперенесенных событий действительно будет потеряна. Но, слава Богу, пока такого не происходило.


Для стартапа чревата ситуация, при которой база данных выбирается без учёта необходимости дальнейшего роста. Некоторые функциональные особенности могут быть не востребованными сегодня, но понадобятся завтра. Менять курс, методику и средства решения задач на этапе стартапа приходится часто.

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

Если вы используете узкоспециализированную базу данных, то теряете гибкость.

В NoSQL, на мой взгляд, важно то, что нельзя делать запросы, которые худо-бедно, но работают. Зато их можно быстро написать и оставить — они будут подсчитаны, и будет результат.

В-четвертых, целесообразно использование базы данных как некоего хранилища или движка для событий.

В "Badoo" я насчитал три частых use-case. Первая группа – это события, которые порождены транзакциями. Их обязательно нужно записать в той же транзакции, что и изменения данных. Они строго последовательны. Второй случай - это события, которые должны надежно доставляться. Лучше пускай одно событие придет два раза, может быть, поздно, но оно дойдет. Третий момент — это события, которые можно потерять. Мы умеем делать так, чтобы одно событие не приходило дважды, но все-таки главное, чтобы оно не было потеряно.

Самый часто встречающийся use-case — это ведение статистики и сбор определенных логов. Отдельные записи, вероятно, можно потерять, но это не главное.

Проблемы двух последних use-case, по-моему, хорошо устраняются при помощи специализированных движков. 


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

У нас в "Badoo" исторически сложилось именно так.


Для важных событий приходилось создавать записи в файл в виде одной строки. Один файл создавался на час, после чего приходилось заменять его другим. На каждой PHP-машине действовал отдельный скрипт, который брал последние созданные файлы и перемещал оттуда события в общую базу данных (или несколько баз данных). В базах впоследствии располагались скрипты, которые производили сбор, обработку и агрегирование данных.

Проблемы заключались в следующем. Одна из них состояла в том, чтобы перемещать данные из "MySQL" между площадками. Вторая состояла в одновременном запуске значительного количества (например, двухсот) скриптов. Все пробуют писать в одну таблицу. Поэтому у нас общий лог, разделенный между 200 соединениями в порядке очереди. Поскольку писать приходилось по кругу, процесс шел очень медленно. Третья проблема была связана с процедурой записи, допустим, гигабайтного файла, которая должна длиться в течение целого часа. Если связь по тем или иным причинам обрывалась, то дальнейшие действия оказывались под вопросом. Стоило ли требуемые события дописывать? Или нужно было удалить файл и потерять час рабочего времени? Мы долго мучились с этой ситуацией и создали собственную систему, которую написали поверх движка "Scribe".

"Scribe"– это простой сокет-сервер, написанный специалистами компании "Facebook". Он является "трубой".

Мы написали свой движок агрегации данных, который даже позволяет нам терять "сырые" данные и брать только обработанную информацию, поступившую за последний час. Если нам нужно, мы пишем в базу только счётчик, регистрирующий необходимое количество событий. Это может происходить с периодичностью, которую мы определим сами. Также возможно сделать "Alter Table" адекватно ситуации, при которой возникают какие-либо новые события или устанавливаются новые параметры событий. В базу данных информация может поступать в один поток. Проблема с двумястами скриптами исключена.

Сетевых соединений становится гораздо меньше. Мы не хотим перегружать сеть. На каждой www-машине, которая генерирует события, стоит "Scribe Demon". Мало того, что запись производится локально. Если машина "отваливается" от сети, то "Scribe" сумеет собирать записи и продолжать писать. Когда связь возобновляется, записи направляются в нужное место. Сокет-сервер у нас никогда не падал. Он отличается простой и гибкостью в использовании. Кроме того, удобство применения подчеркиватся возможностью back-end-хранения данных.

Самое главное – "Scribe" очень быстрый. Все сокет-соединения "Scribe Demon" уже открыты. Запись производится в один сокет, которое по открытому коннекту передается дальше по частям этого "дереву". Задержки остаются на уровне миллисекунд. Подобным образом мы пересылаем событие с back-end на некую скриптовую машину, которая далее размещает поступившие данные в БД. Также с помощью "Scribe" мы перемещаем данные между площадками.

Мой пятый совет касается поиска.

Как правило, в стартапах, на мой взгляд, имеет место два сценария. Либо решить задачу своими силами быстро, просто, но плохо (данный подход применяется в 99% случаев). Либо все-таки использовать какой-либо специализированный движок (возможно, на базе Java или C++). Самый популярные варианты – Lucene/Solr/ElasticSearch и, конечно, "Sphinx".

Появляется граница слова, которая ищет слово "one". Не слово "gun". Здесь можно найти, допустим, слово "gun". Приглашаю вас изучить исследования Билла Карвина. Затем переключаемся на "full text index MySQL" и обратные индексы. Все хорошо работает, но процедура поиска вызывает нарекания. Интеграция стоит небольших затрат, но конечный результат неудовлетворительный.

«Percona» провела сравнение между «MySQL» и «Sphinx». Статьи «Википедии» были индексированы на обычном Commodity-сервере. 2,5 миллиона статей, 15 гигабайт «сырого» текста. Sphinx-индексация длилась всего 20 минут. Что касается «MySQL», то даже спустя шесть часов индексация не была завершена.

Поэтому, пожалуйста, используйте в стартапе специализированный софт. Интегрируется не требует крупных затрат, разработка довольно проста. Настройка производится заранее.

Специализированное программное обеспечение предоставляет разработчикам гораздо больше возможностей. Стоит упомянуть о такой возможности, как создание "живого" индекса или очень быстрое удаление документа из базы. Самое главное – качество поиска становится существенно выше.

Шестой совет: должна быть сильная "consistency".

Я специально не стал писать слово "consistency" на русском, потому что "связанность" недостаточно полно раскрывает смысл. Нас учили, что должна быть третья форма и данные необходимо связывать. Все должно быть в одном месте, атомарно и шикарно.

На самом деле сильная «consistency» в вебе нужна не всегда. Кроме того, ее довольно сложно достигнуть. Когда данные перестают помещаться на одном сервере, пожалуйста, используйте грамотный подход посредством «consistency».

В этом плане надо отдать должное «MySQL» и поблагодарить людей в майках «MongoDB». Они делают полезное дело. Зачастую нам все равно, сразу ли увидит Вася комментарий Пети. Главная задача – иметь связанные данные, выдаваемые конкретно одному пользователю. Как это происходит, пользователей совершенно не интересует.

Существует полезный подход – выборочное "выдергивание" записей в базу. Часто имеет место неправильное решение, при котором большое количество обновленных однородных данных пишутся в базу данных, "затирая" самих себя. Происходит сохранение нового состояния.

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

Денормализуйте, денормализуйте, денормализуйте! Это дает прекрасный прирост производительности. Главное – производить изменения, основываясь на здравом смысле.

Есть мы используем SQL-базу данных, то позвольте я переведу часть статьи про нее из английской Википедии. «SQL – база данных. Это консистентное транзакционное хранилище данных, которое гарантирует, что данные хранятся в схеме, которая использует реляционную алгебру для доступа к нормализованным таблицам».

Далее, например, приходит юный системный архитектор и происходит следующее. Мы соединяем ведомый сервер с ведущим, происходит репликация. «Сonsistency» не потеряна. Потом занимаемся mem cache, учитывая возможные высокий нагрузки. К ведомым серверам подключаем другие ведомые серверы, организуем репликации от репликаций, не забывая о шардинге. Когда начинаются проблемы с "Alter table", создаем один столбец на целую таблицу, в котором хранится "JSON blob". Именно он содержит все данные из таблицы.

Что было в самом начале? Много данных, с которыми неумело обращались.

Что стало?

Осталось только "Data store", хранилище данных. И волшебное слово "access". Действительно, доступ остался.  

Последний, седьмой, совет касается использования хорошо изученных инструментов. Неизвестность, как известно – это опасность. Когда вы используете свои готовые наработки, скорость разработки выше. Вам уже знакомы все «подводные камни» и «грабли».

Также, пожалуйста, не поддавайтесь моде на SQL. На мой взгляд, SQL "распиарен", как Дима Билан. Почему?

Во-первых, существует огромный маркетинговый прессинг, "розовый пар". Во-вторых, на мой взгляд, имеет место психологический фактор популярности. Что я имею в виду?

Возьмем условновного программиста-пятикурсника из стартапа. Как обращаться с базой данных, он знает. С MySQL работал. PostgreSQL он "трогал". Однако он очень плохо разбирается в "acid". Кап-теорема ему совершенно незнакома. О третьей нормальной форме он слышал на третьем курсе, но прогулял лекцию. Транзакции когда-то использовал, но не понял зачем. Поэтому мы в стартапе транзакции не используем. А зачем? Все работает. Что касается NoSQL, то программист пытается делать вид, что знания о базах данных не нужны, как и специалист по базам данных.

Какая база данных станет для подобного сотрудника идеальной?

Идеальная БД хранит объекты классов приложения (вроде "JSON blob" или "PHP serialize") в таком виде, в каком я работаю с ними в программе. Кроме того, идеальная БД работает быстро и заботится обо всем остальном сама. 

Когда в стартапе происходит выбор базы данных, технический менеджмент сторонится этой процедуры, доверяя ее программистам. На самом деле это задача технического менеджмента. Почему? Необходимо оценить все риски, окончательную стоимость и принять обоснованное решение из расчета на будущее. В действительности базу данных выбирает программист-середнячок. Что он выбирает? Что больше всех рекламируют: NoSQL. Однако если мы рассматриваем проблему "SQL без NoSQL", то нужно иметь в виду хотя бы следующие пункты.

  • Чаще всего, NoSQL – это запись в один поток. Новые записи ждут своей очереди. Если даже запись достаточно велика, пока она не будет обработана до конца, процесс дальше не пойдет.
  • Использованием функционала "memory-mappet files", в файловой системе, в который есть свои проблемы с IO scheduling. Непонятно, как он потом "свопит" и "высвопливает" это дело из памяти. Как вообще он работает с памятью. Просто это не рассчитано на базу данных. У этого функционала нет понимания того, с какими данными он работает, какие данные будут нужны дальше. Поэтому он работает, как хочет, а база данных тоже работает, как хочет.
  • Как правило, на один индекс приходится один запрос.
  • Если есть шардинг, то его нельзя назвать гибким и быстро разворачиваемым.
  • Тюнинг производительности осуществляется только на уровне операционной системы. Зачастую атомарность отсутствует даже на уровне одного запроса.
  • Неудовлетворительный мониторинг и статистика. Чаще всего приходится писать много однообразного кода, который имитирует сложные запросы.

Но есть и плюсы.

  • NoSQL чаще всего быстрее SQL-баз.

  • Ей очень просто развертывать (особенно дешевый шардинг).

  • Схемы нет, поэтому "Alter table" – больше не проблема.

Что можно сказать насчёт SQL?

  • Оно медленнее.

  • Сложнее.

  • Имеется много каверзных настроек.

  • В редких случаях работа протекает по непредсказуемому сценарию. С SQL нужно уметь обращаться.

  • Данная база более популярна и очень хорошо изучена. Ей занимаются двадцать лет. Основы реляционной алгебры были заложены еще в 1970-х годах. Язык у всех совпадает на 80%. Можно быстро переключаться между базами данных. Разработчику придётся не очень сильно переучиваться.

Каковы плюсы использования SQL?

  • Это очень изученный, стабильный продукт, консультацию по которому могут дать множество экспертов на рынке.

  • Хранение данных зависит от вида данных.

  • Множество рычагов оптимизации и сторонних инструментов. Набор полезных свойств, которых пока нет в NoSQL («constraint», триггеры, хранимые процедуры и прочее).

  • Full ACID обычный или ACID условный.

  • Множество полезных индексов. С их помощью можно решать неординарные задачи (например, выполнять поиск точки на карте). Геопоиск, Р3, B3, Gin, GiST, hash-индексы. Можно создавать индексы с собственной функцией расстояния и т.д.

Продолжим список преимуществ SQL.

  • Возможность использовать джойны.

  • Эффективный оптимизатор запросов.

  • Возможность параллельного использования нескольких запросов. Данная технология прекрасно масштабируется по ядрам.

  • Подзапросы иногда тоже исполняются параллельно.

  • Многоуровневое кэширование.

  • Статистика. Мониторинг.

  • Самое главное: можно писать сложные, но плохие запросы. Зато это позволяет не писать длинный код для приложений.

А выводов нет. Нужно думать своей головой.

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

Вопросы и Ответы

Реплика из зала: Если я в своем проекте полностью откажусь от SQL в пользу NoSQL, означает ли это то, что я буду испытывать проблемы с масштабированием и целостностью данных?

Сергей Аверин: Может быть, получите, может, нет. Это во многом зависит от выбираемого решения, построенной архитектуры.

Реплика из зала: Я, наверное, прослушал, почему джойны – зло. Что нужно использовать вместо них?

Сергей Аверин: Когда вы сталкиваетесь с высокими нагрузками, вы не найдете распространенных баз данных, где бы джойны быстро и эффективно работали. Они всегда требуют довольно много ресурсов памяти, т.к. требуется обрабатывать два больших массива данных. В итоге снижается производительность. Используя джойны, справиться с высокими нагрузками, к сожалению, не получается.

В "Badoo" джойны запрещены как класс. Это было волевым политическим решением.

Реплика из зала: Получается, тогда нужно делать снимки?

Сергей Аверин: Краткий ответ – медленно работают.

Реплика из зала: А как вы боретесь с проблемой?

Сергей Аверин: Если что-то можно хранить в mem cache, храним в mem cache. Или используем в работе, особенно при взаимодействии с малыми массивами. Малый массив надо выбрать в память приложения и «склеить» самостоятельно по ID. Выбрать большой массив или во время выборки доклеивать ручками уже при выводе. Просто делать джоинт в процессе PHP. Либо можете осуществить денормализацию и сохранить данные, обработанные джойнами.

Реплика из зала: Хотел уточнить. NoSQL – проще и быстрее, но не так качественно. SQL – сложно и медленно, но лучше использовать его. NoSQL – это "бензопила". SQL – "молоток". Если человек бьет себе по пальцам молотком, не знает Кап-теорему, это не значит, что он напишет что-то хорошее на SQL.

Сергей Аверин: Рассмотрим широкий круг проблем стартапа. SQL предлагает решение в стиле "есть большой, хороший комбайн, с помощью которого нужно научиться "готовить". Необходимо ввести там три (условно) правила.

Как это реализовано у нас в компании? Мы не используем джойны, стараемся не использовать ложные запросы и хранимые процедуры. Все вместе это позволяет нам худо-бедно обслуживать, по-моему. семь миллионов наших пользователей в день заходящих.

Соответственно, NoSQL предполагает более качественное решение конкретно одной узкой задачи, не предлагая средств для решения остальных вообще. С SQL можно научиться "готовить", при этом он будет хорошо и прекрасно работать в отношении широкого круга задач.

Реплика из зала: Можно использовать несколько NoSQL-решений для решения конкретных задач. Они будут быстрее работать, чем...

Сергей Аверин: Можно. Но разработчики стоят очень дорого. Представьте себе: наняли разработчика, который знает пять разных NoSQL-баз данных, готов их сравнивать между собой, знает все плюсы и минусы. Какую часть Кап-теоремы они реализуют и т.п. Когда у вас стоит задача нанять сто сорок офисных программистов, это сделать не реально.

Реплика из зала: Вы сейчас нарушаете первый же пункт, забегая вперед.

Сергей Аверин: Мы – большая компания.

Реплика из зала: Ну, так, а вы для кого доклад делали? Для больших компаний, которые хотят стать еще больше?

Сергей Аверин: В начале доклада что написано?

Реплика из зала: "Семь советов стартапам".

Сергей Аверин: Да. Если интересно, могу рассказать, что происходит, когда он превращается в большую компанию. Но здесь написано: "Семь советов стартапам". Лучше в стартапе использовать базу данных широкого профиля, позволяющую решать множество задач разом.

Реплика из зала: К вопросу о будущем. Стоит ли использовать базы данных, не располагающихся в открытом доступе? "DB2", "Informix", "Oracle"...

Сергей Аверин: Если вы покупаете "коробочный" продукт, где за вас подумали, это решение действительно устраняет ваши проблемы, т.к. за ним есть хорошая поддержка, профессионалы и прочее. Если вы пытаетесь сами интегрировать какие-то отдельные элементы, взять просто платную базу данных – скорее всего, это того не стоит. Большей частью нет.

Понимаете, в чем дело… В стартапе всегда есть одна болезнь. Она называется: "Мы решим важную техническую задачу, а бизнес-задачами заниматься не будем". Тогда сделайте проект, выложите его в открытом доступе и разместите на "Github". Если вы не занимаетесь бизнесом, лучше не рискуйте. У вас могут однажды закончиться деньги, если будете платить за базу.

Мы в "Badoo" (это большая компания) используем дорогую базу данных "VectorWise". Она используется для того, чтобы считать статистику по очень большому количеству статистических данных для проведения маркетинговых исследований и отчетов в лондонском офисе. Все остальное делается на MySQL. Еще мы использовали "Redis", часто используем "Handler Socket". Также остались "крохи" "MongoDB".

Но у нас паттерн NoSQL всегда следующий: перенеси работающую задачу на него и если будет работать лучше, то оставить. Так получилось, что "Redis", как и "MongoDB", у нас не остался, в отличие от "Handler Socket". Правда с с ним проблем было столько, что я месяца три работал на библиотекой. Мы написали для него свой "клиент".

Реплика из зала: Что вы скажете о базе данных PostgreSQL?

Сергей Аверин: На мой взгляд, проблем там несколько. Я лично знаю только одну. Я бы сказал, что она, может быть, определяет только треть будущего. Любая подходящая операционная система может выдержать тысячу с лишним потоков на обычном сервере (может быть, две-три тысячи потоков). Но не может выдержать тысячу процессов. MySQL делает поток на соединение.

А PostgreSQL не рассчитана на такие дела. Она создает новый процесс на каждое соединение. Получается, что большое количество соединений нельзя открыть.

Поэтому некоторые начинают писать свои демоны, которые поддерживают соединения. Короче, с PostgreSQL, мне кажется, справиться с высокими нагрузками довольно проблематично. Но отдельные задачи она решает лучше, чем MySQL. В ней выбор индексов шире. Она более настраиваемая. Можно создавать некоторые гео-вещи, которых в MySQL нет и не предвидится. В общем частные задачи решаются лучше, а общая - хуже.

Реплика из зала: В "Badoo" используется MySQL?

Сергей Аверин: Сейчас используется Percona-сервер. Но где-то остался и MySQL.

Реплика из зала: Есть свои задачи, которые приходится решать. Как вы решаете задачу с необходимостью изменения схемы базы данных?

Сергей Аверин: Мы делаем код такой, чтобы он был совместим с обоими из предыдущей версии, схемы и со следующей версией схемы. Затем, есть админы, готовый функционал, который эти схемы меняет в шардах. В несколько потоков, но по очереди. Поскольку у нас двести серверов, которые хранят юзерские данные, невозможно взять и сделать "alter table" на всех – повиснет. Поэтому это делается вечером, когда нет трафика.

Схема меняется после того, как был выложен код, который умеет работать со старой и новой схемой. Стараемся делать вот так. В 99,9% случаев весь функционал у нас делается вот так. Есть возможность задетектить обновленные. База данных обновилась, или "демон", которым мы коннектимся, обновился. Используется какая-то другая ветка кода.

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

Реплика из зала: Стартап неизбежно будет изменять свою архитектуру, и, возможно, не раз. Каков критерий и когда выбрать нужный момент?

Сергей Аверин: Пока не измеряешь, ты не контролируешь процесс. Нужно в какой-то момент начать измерять ("Capacity" серверов, загрузку LA и все такое). Про это у нас был отличный доклад на прошлом РИТе.

Есть прекрасная книжка, называется "Искусство масштабирования". Искусство "Capacity planning". Советую ее прочитать.

Реплика из зала: Если я правильно понял, у вас собственная реализация репликации MySQL-серверов.

Сергей Аверин: Да.

Реплика из зала: Почему вы отказались от стандартной, в чем преимущество вашей собственной реализации?

Сергей Аверин: Было две причины. На тот момент каких-то нужных свойств не было, когда все это проектировалось (2006-й год). Во-вторых, нужна была репликация с дата-центра "Worldness". Разная репликация между дата-центрами - разная репликация на площадке. Поэтому так исторически сложилось, что она была сделана скриптами на PHP. Для этого есть пустые сервера, которые хранят репликационные данные. Если они закончатся, таблицы опять опустеют.

Реплика из зала: Что вы можете сказать насчет используемой платформы?

Сергей Аверин: Этот вопрос нужно задать Алексею Рыбаку. Платформой занимается он. Я занимаюсь разработкой программного обеспечения, работающего на компьютерах. 

Реплика из зала: Я хотел бы вернуться к теме джойнов. Вы сказали, это и добро, и зло одновременно. У вас джойнов в проекте "Badoo" нет принципиально вообще или они используются только в новом коде?

Сергей Аверин: Их принципиально нет с самого первого дня проекта. Была сильная команда, которая до этого делала "Mamba" и знала много подводных камней. На самом деле, джойны есть, но в 0,000001 случае из ста – там, где нет высоких нагрузок.

Реплика из зала: А что это за случай?

Сергей Аверин: Это когда нужно "джойнить" с четырьмя рядами. Например, у вас есть множество сообщений, вам нужно выбрать последние сто и выбрать название папки, в которой он лежит. А этих папок у вас всего четыре: "Входящие", "Исходящие", "Удаленные" и "До свидания". Поэтому в таком случае мы используем джойны. Их очень мало.

Каждому разработчику всегда нужно соизмерять объемы.

Реплика из зала: Еще про хранение процедур вы рассказали интересно.

Сергей Аверин: Это принципиальный момент: в первую очередь проблемы возникают с их синхронным обновлением. Где-то они поменялись, а где-то – нет.

Реплика из зала: Как используется транзакционность?

Сергей Аверин: Только в рамках шардинга. Обновляешь один шард, он транзакционно обновляется. Все остальное, что нужно обновлять, записывается в очередь. Есть скрипт, который берет с одного сервера из этой очереди событие и пытается транзакционно "накатывать" на другой сервер.

Комментарии

Нет ни одного комментария

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

Возможно, вам будет интересно:

Сергей Аверин

Сергей Аверин

Руковожу разработкой проектов в Баду. Программирую server-side. Конференционный маньяк. Среди проектов, которые я делал — Хабрахабр, dirty.ru, trendclub.ru. Специализируюсь на больших/сложных веб-проектах.

twitter: twitter.com/ryba_xek
facebook: facebook.com/ryba.xek

Сергей Аверин (Badoo) рассказывает о постоянных соединениях (pconnect) и проблемах их внедрения.

Дмитрий Сатин

Дмитрий Сатин

Советник министра в Министерстве связи и массовых коммуникаций Российской Федерации, евангелист юзабилити

Дмитрий Сатин объясняет, как ввести команду в состояние потока и не потопить ее.

Евгений Эльцин

Евгений Эльцин

Разработчик ПО в Google.

Евгений Эльцин (Google) рассказывает об исполнении нативного кода в браузере посредством использования Native Client.