Системы асинхронного обмена сообщениями

11:26, 12 августа 2008
Количество запросов к барахолке постоянно растет . Чтобы обеспечить бесперебойную работу и должный уровень производительности, нам приходится увеличивать парк серверов и применять различные методы для хранения и обработки данных. Фактически на барахолке используются 3 типа хранилищ данных: реляционная база данных (MySQL в репликации), NFS-кластер (для статических ресурсов) и сервер очередей сообщений ActiveMQ (два брокера для отказоустойчивости).

В этой технической статье мы опишем, что такое ActiveMQ и почему мы его применяем на барахолке.

История


Когда говорят о масштабируемости рано или поздно всплывает тема асинхронного обмена сообщениями. Сама идея стара как мир и использовалась еще в 60-х годах в таких языках как SmallTalk. Но большую популярность этот подход получил в среде Java в виде спецификации JMS. Сейчас существует уже достаточное количество очередей сообщений, которые вы можете использовать абсолютно бесплатно. Для нашего проекта мы выбрали ActiveMQ. Фактически это транзакционная база данных со своим форматом хранения, которая оптимизирована под обработку очередей. Общая идея состоит в том, что одни потоки (producers) пишут сообщения в очередь, а другие их разбирают (consumers). Producers и consumers ничего друг о друге не знают. Единственное по поводу чего существует договоренность – это адрес очереди и формат сообщений. В очередь могут писать, когда никто из нее не читает и наоборот.

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

Помимо вышеприведенных причин есть еще одна более скрытая и серьезная проблема, которая проявляется в системах где весь запрос обрабатывается синхронно. Большинство современных web-серверов являются потокоориентированными. Это значит, что пока поток не обработает запрос пользователя, большинство связанной с запросом информации не может быть выгружено из памяти. Это сказывается на времени обработки запроса и на интенсивности использования памяти сервера. Поэтому «синхронные» приложения хуже приспособлены для обработки большого колличества параллельных запросов. Уже сейчас существуют наработки в области seda-архитектуры, которая позволяет решить эти проблемы, но пока что ее использование не распространено в силу малого опыта использования в высоконагруженных приложениях.

На практике


На практике это выглядит следующим образом. Пользовательские запросы разбиваются на фазы и некоторые из них выполняются асинхронно. Благодаря этому сокращается время обработки запроса, потому что мы не ждем, пока асинхронные фазы полностью выполнятся. Например, запись статистической информации не настолько важная функциональность, чтобы пользователь ждал, пока вы обновляете информацию в хранилище статистики. Можно показать пользователю интересующую его информацию сразу, а статистику записать позже, когда будут свободные ресурсы (может быть даже через несколько часов). Вы можете мне возразить: «да там всего то, одну запись вставить в БД». Ну, во-первых, если статистики у вас много, то вы будете хранить ее в агрегированном виде (иначе для построения отчетов вам потребуется изрядная доля терпения). А это значит, что вы вставляете запись в таблицу, только если ее там еще нет. Иначе вы обновляете таблицу. Несмотря на то, что в MySQL есть инструкция «REPLACE», которая вроде как объединяет эти два действия, на самом деле на стороне сервера выполняется то же самое – условная вставка с обновлением. Во-вторых, обновление статистики может происходить только в том случае, если пользователь не просматривал это объявление в течение последних пяти минут. Это подразумевает еще одну вспомогательную таблицу и еще одну проверку со вставкой. В-третьих, непонятно как нам поступать, если по каким-то причинам база данных со статистикой не доступна. А в один прекрасный вы можете обнаружить что «безобидный» сбор статистики тормозится интенсивным чтением из другой таблицы. А что поделать, — жесткий диск один.

Вопреки расхожему мнению, не все эти проблемы можно решить путем покупки новых жестких дисков, процессоров и памяти. Один Apache, например, не выдерживает больше 4000 параллельных запросов. Я бы сказал, что эта цифра взята с потолка. Если вы постараетесь, то выжмите из него и больше. Но смысл в том, что эта цифра конечна. Рано или поздно придется столкнутся с горизонтальным масштабированием.

Другими словами, с реляционными базами данных мы имеем следующие основные проблемы:

  • невозможно создать структуру базы данных, которая была бы оптимальна и для чтения и для записи;

  • запись в базу данных очень тяжело распараллелить;

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


Как поможет очередь?


Но если мы можем сделать запись в хранилище асинхронным, то нет смысла оптимизировать базу данных под запись. Так как запись будет производиться в отдельном потоке, — пользователь не будет заблокирован записью и получит нужные ему данные, даже если хранилище статистики недоступно в момент запроса. Следовательно, мы можем предоставлять сервис даже в моменты downtime’а некоторых ресурсов (причем без потери данных).

Производительность


Средствами реляционной базы данных запись масштабируется очень плохо. Даже eBay, у которой одна из самых крупных инсталляций TeraData в мире, знает это. Очереди сообщений, с другой стороны, очень быстры по своей натуре. Одной из причин тому является то, что очередь – это одна из немногих структур данных, для которой возможна относительно простая неблокирующая реализация. Это позволяет работать с очередью в условиях высокого concurrency. Но даже если вы упретесь в производительность одного сервера, очередь, в отличие от реляционной базы данных, очень просто распараллелить. Достаточно запустить еще одну инстанцию брокера и распределить посылку сообщений между обоими брокерами. Благо распределение нагрузки и failover в ActiveMQ делаются стандартными средствами.

Отказоустойчивость


Основной проблемой с отказоустойчивостью реляционных баз данных является то, что ее надо реализовывать самому. И не всегда ясно, каким образом. Репликация может давать значительный лаг, что не дает просто так отбросить вышедший из строя master и просто использовать slave, — может оказаться, что мы начали использовать неактуальную реплику. Еще одним решением может быть MySQL Cluster. Но он до сих пор не очень популярен и имеет ряд серьезных ограничений.

У очередей сообщений все иначе. Вы можете довольно просто связать два брокера в failover кластер. Так что даже при выходе из строя одного из серверов в целом очередь будет все еще доступна, так как сообщения будут отсылаться через второй брокер. Существует также топология называемая «Network Brokers», которая подразумевает, что сообщение может быть отмаршрутизировано чрез несколько брокеров прежде чем оно достигнет адресата. Это позволяет немного упростить разработку приложений. К сожалению, данный функционал все еще остается очень нестабилен.

Ложка дегтя


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

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

14 комментариев

sergei05    14:56, 12 августа 2008
Это вы сейчас с кем разговаривали?
john333 +102    15:18, 12 августа 2008
В связи с тем, что старые темы блога Администрацией не просматриваются, пишу в «топе».
Очень напрягают «монетчики». Возможно ли сделать так, чтобы при занесении в «черный список» некоторых пользователей, их сообщения не отображались? Или по-другому — возможно ли реализовать на Барахолке «игнор-список»?
«Фальшивомонетчики» — это уже просто спамеры и флудеры какие-то на Барахолке ;-) Дихлофосом не пробовали? :-)))
john333 +102    15:21, 12 августа 2008
Ну хоть фильтр на аукционах поставьте. ПОЖАЛУЙСТА! Платной эту услугу сделайте — я согласен.
Myxomor +59    16:48, 12 августа 2008
Очень нужен фильтр! Ходить по разделам — не выход. А так поставил, что интересно и смотришь!
vich +32    20:37, 12 августа 2008
А про коэффициент диффузной корелляции..? Забыли?…
Садись, Фарпостов, ДВА!!!
mizaar +128    12:22, 13 августа 2008
да, я смотрю у людей нет опыта в эксплуатации (а тем более разработке) промышленных СУБД…

вы меня конечно извините, но "Основной проблемой с отказоустойчивостью реляционных баз данных является то, что ее надо реализовывать самому. " это пипец…. то, что вы имели дело только с MySQL не дает вам право утверждать, что отказоустойчивость в реляционных СУБД возможно осуществить только занимающей время репликацией.

«Ну, во-первых, если статистики у вас много, то вы будете хранить ее в агрегированном виде (иначе для построения отчетов вам потребуется изрядная доля терпения)» — жесть… никто не в нормальных системах не пересчитывает статистику в он-лайн, аггрегации пересчитываются раз в интервал

«жесткий диск один.» — ЭТО КАК?????

"непонятно как нам поступать, если по каким-то причинам база данных со статистикой не доступна. " — жесть.

Вобщем, как человек, который около 4х лет разрабатывал приложения для СУБД (и хранилища данных, и web) заявляю — статья дилетантская. И если судить по проблемам барахолки , то занимаются ее обслуживанием они же, ибо в мире есть гораздо больше проектов, выдерживающих большую нагрузку, но не мающихся прикручиванием пятого колеса к веб-серверу, а просто делающих свою работу хорошо.

Спасибо за внимание, кончел.
baza_developer    13:06, 13 августа 2008
К сожалению, практика показывает что все не так просто. Все крупные ресурсы такие как flickr, livejournal, tweeter и прочие используют как раз MySQL. Отчасти из-за низкой стоимости владения, отчасти из-за того, что какую бы «мега супер крутую версию Oracle/MsSQL/Terracota» вы не использовали, если хотите добится высокой производительности все равно придется заниматся sharding'ом. И простой partitioning вас не спасет. Может быть для warehouse все иначе, но в web'е это практика более десятка крупных проектов (см. http://highscalability.com/).

По-поводу аггрегации. Все верно, такие вещи как OLAP/OLTP никто не отменял. Но это существенно усложняет проект в целом, особенно когда мы говорим о базе данных в которой нет нормальной поддержки OLAP. Есть ситуации (наша в частности), в которых OLAP излишен, а статистика нужна в realtime. Альтернатива? Она описана.

И конечно же не имелось в виду, что жесткий диск именно один. Имелось ввиду, что производительность любой БД рано или поздно упирается в жесткий диск, запись на который тяжело увеличить, скажем, в 10 раз. А это все говорит о том, что для проекта с интенсивным ростом надо вкладыватся не в вертикальную масштабируемость, а в горизонтальную. И как можно больше обработки производить асинхронно. К сожалению, современные базы данных плохо масштабируются горизонтально, даже Oracle.
mizaar +128    14:40, 13 августа 2008
то, с какими проблемами сталкиваются DBA LJ, filckr , etc. , вместо того, чтобы взять и переписать код на промышленную СУБД, а не ставить подпорки к старому, можно почитать в их блогах.

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

спасибо за ответ.
baza_developer    15:14, 13 августа 2008
С тем что масштабируемость — это в первую очередь задача разработчика, а не базы данных, я согласен. Никто и не высказывал иного мнения. База данных может лишь дать небольшой запас по производительности. Но от того какой сервер базы данных испольуется (и как она спроектирована), зависит то, какие усилия надо потратить чтобы получить нужный уровень масштабируемости.

Основная мысль данной статьи в том, что помимо реляционных баз данных есть и другие. Заточенные под решение узконаправленных задач, но позволяющие решать эти задачи более эффективно. Очереди сообщений — это одна из подобных (есть еще документо-ориентированные, которые тоже популярны в определенных кругах). У них свою нюансы, свои плюсы, свои минусы. У нас в проекте мы нашли место одной из таких и успешно пользуемся предоставляемыми ею выгодами.
mizaar +128    14:41, 13 августа 2008
под словом расширяемость имел ввиду масштабируемость
baza_developer    17:20, 13 августа 2008
Вообще, было бы интерестно услышать как вы справляетесь с проблемами описанными выше. Я так понял, что у вас процесс и технологии более соверешенны.
neocubiavl +381    15:17, 13 августа 2008
Не совсем понятно для кого написана статья. Я же не пишу вам в блог с какими мне трудностями мне приходится сталкиваться при продаже лотов :) :) :)
Впрочем есть одна трудность (читай баг): при добавлении нового лота в разделе «Активные аукционы» лот появляется, но без названия. Присутствует фотография, статистика, цена, но вот название лота появляется намного позже. Очень не удобно, особенно когда выставляешь несколько похожих лотов…
malex +19    23:57, 13 августа 2008
mizaar ты не прав, статья действительно о другом, а в остальном
oracle, mssql и папа римский не спасут, и если ты 4 года работал в этой области то орбит жуй :)
swan7575 +29    17:52, 15 августа 2008
чё вы так все паритесь?
меня всё устраивает.
только вот, очень хотелось бы, чтобы сообщения людей в черном списке не приходили адресату.

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