Wednesday, May 21, 2008

Map/Reduce своими руками — Apache CouchDb

 

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

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

С другой стороны, в большинстве случаев, когда речь идет о десктопных (или веб-) приложениях, где не нужно ворочать миллионами примитивных записей,  а приложение работает с относительно высокоуровневыми, сложными объектами, суть "дизайна и проектирования баз данных" заключается в повторении двух действий:

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

б) затем упорно собирать эти поля в объекты обратно, пользуясь четырехэтажными JOIN'ами, мегабайтами кода врапперов, кривыми и не очень слоями ORM — в зависимости от квалификации разработчика, в общем, всячески преодолевать пресловутый O/R impedance mismatch. При этом и рукописные JOIN'ы не показывают чудеса производительности и гибкости, а сгенеренные автоматически умным слоем врапперов — тем более.

SalesLogix v7 Database SchemaВ принципе, ORM-библиотеки в динамических языках (см. SQLAlchemy) довольно приятны в обращении, однако и они не позволяют элегантно решить еще один болезненный вопрос — с апгрейдом схемы.

 

В общем, немало приложений используют базы данных для хранения сложных структур данных, и при этом действительно сложные запросы с использованием внутренних зависимостей к этим данным им на практике нужны редко, или вообще не нужны (если не считать мега-JOIN'ов для того, чтобы просто обратно выковырять эти свои структуры из БД). Похоже, обычная RDBMS мало подходит для них — упомянутые выше проблемы довольно болезненно решаются, а миллионы человекочасов тратятся разработчиками БД на реализацию других, бесполезных для них возможностей.

Одним решением являются объектно-ориентированные хранилища, они действительно становятся довольно популярны и заслуживают отдельного разговора. Они прозрачно решают проблему с ORM, но, если говорить о веб-приложениях (которые весьма интересуют нас в свете обещаной новой версии defun.ru :), объектно-ориентированные базы это таки не совсем то, что доктор прописал — они не решают проблем горизонтальной масштабируемости и распределенности данных, да и веб — это прежде всего много текстовой информации, неплохо было бы как-то учесть и это.

Логотип CouchDb

Итак, CouchDb — документоориентированная база данных. Хранить она умеет документы — объекты, состоящие из кучи полей с произвольной структурой. У каждого документа есть только два обязательных служебных поля: имя и версия, имена уникальны и находятся в линейном пространстве — представьте себе гигантскую директорию с файлами-документами, вроде такого:

{
 "_id":"63086444D554D3094C080F96D5005B03",
 "_rev":"1837603925",
 "author":"lrrr",
 "tags":["baz","test","ru"],
 "url":"http:\/\/incubator.apache.org/couchdb",
 "title":"couchdb home",
 "description":"boo boo ba ba",
 "type":"story",
 "comments":1,
 "votes":2
}

Версии нужны для организации параллельного доступа к базе данных — вспомните как работает ваша система контроля версий — если мы хотим изменить документ, мы просто берем его, меняем и пытаемся положить обратно — если за это время его версия не поменялась, все отлично, если поменялась — можно просто попробовать внести те же изменения еще раз, с новым документом, или еще как-то сделать merge (в зависимости от приложения). Это называется optimistic locking, основной плюс — никто не блокирует документ на время редактирования, и поэтому не нужно ждать разблокировки. Кстати, такой механизм может применяться и в некоторых современных RDBMS, только на уровне строк в таблице (см. http://www.google.com/search?q=%22row+versioning%22).

Архитектура CouchDb Интерфейс к CouchDb — исключительно HTTP, исключительно  REST, а ответ от сервера приходит в формате JSON. Поначалу это несколько настораживает — не самый эффективный протокол, но с учетом того что высокоуровневые документы хранятся в ней целиком, делать по 5-10 запросов к базе на каждый чих и не нужно. А плюсов куча: во-первых, любой язык умеет работать с HTTP и JSON (а если не умеет, легко научить), во-вторых — легко отлаживать, в третьих — CouchDb понимает HTTP Etag и If-None-Match, а значит можно без особых усилий прикрутить к базе HTTP кэш. 

Зато масштабироваться вширь все должно отлично — в конце концов, примерно по такой схеме построены и Amazon SimpleDb, и Google BigTable. Удивительное, кстати совпадение, но и SimpleDb, и CouchDb написаны на эрланге ;)

 

 map & reduce

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

Естественно, что менее структурированные данные обрабатывать сложнее, и, раз уж мы так заботимся о масштабируемости — запросы эти тоже должны легко распределяться по кластеру серверов БД. Для этого CouchDb использует паттерн map/reduce, описаный в известной статье инженеров Google.

На практике выглядит это так: на сервере, в специальных документах хранятся view-функции (собственно map() и reduce()), преобразующие набор документов нужным образом, и к ним можно обращаться с помощью того же REST интерфейса. Вычисляться они умеют постепенно, с сохранением промежуточных результатов, то есть, если между двумя вызовами view добавился или изменился один два документа, то функция будет вызвана только для них. Пишутся они на JavaScript, но можно несложно подключить вместо этого python/ruby/что-то еще.

В качестве дополнительного бонуса — поддержка полнотекстового поиска по документам, с помощью любой внешней библиотеки (пока авторы прикрутили к CouchDb поисковик Apache Lucene).

* * *

В конце обычно принято немного попинать рассматриваемую технологию, но CouchDb мне пинать пока жалко — слишком приятное впечатление производит. Хотя, конечно, это пока всего лишь альфа-версия, со всеми вытекающими последствиями (reduce, скажем, появился в транке три дня назад). Да, она очень небыстрая — пока умеет обрабатывать порядка десятков insert'ов в секунду (если не использовать режим bulk update) и да, она жрет очень много дискового пространства — так как все промежуточные версии документа сохраняются, если их периодически не удалить специальной функцией "Compact Database" — впрочем, это можно делать параллельно, не останавливая приложение. Однако для альфы система весьма стабильна и уже имеет, среди всего прочего, очень приятный и функциональный веб-интерфейс для администрирования и разработки.

 

Ссылки:

 

27723148.0f886b0078628df55b2305efb1cb3729.1211322056.6554977ddd1d9ebd9f3e14154e6e8540

27 comments:

Denis Gorodetskiy said...
This comment has been removed by the author.
Denis Gorodetskiy said...

спасибо за отличный обзор. руки чешутся попробовать эту бд.

ясно, что все это хозяйство пока тормозит и глючит, но идея автоматического горизонтального масштабирования - золотая!

почему бы не запостить этот обзор на хабр, ну может быть, для увеличения популярности блога?

Denis Gorodetskiy said...

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

lrrr said...

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

> но идея автоматического горизонтального масштабирования - золотая!
Ну оно там не совсем прям автоматическое, но все ориентировано на то чтобы его облегчить.

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

Да, на хабр запостил :) (ужс кстати -- айтишный сайт не понимает даже закрытого тега <br/> в посте)

Denis Gorodetskiy said...

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

FX Poster said...

lrrr, а ты что-то можешь сказать про StrokeDB?

lrrr said...

FX Poster>
Ничего конкретного :) Разработчики вроде качественные, но проект очень молодой пока. Ну и сильно на руби все завязано (я не понял, есть ли у них не-ruby API)?

Есть еще кстати FeatherDb.

JanL said...

Hello,
I used Google's automatic translation since my Russian is a bit rusty (or so) and sorry if I reply in English.

Thanks for the nice write-up and fair evaluation of CouchDB. If you run into any problems, please let us know (either on the mailing lists or on IRC).

Thanks again,
Jan
--

dr-begemot said...

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

Есть следующая задача:

Система А предоставляет web-интерфейс для пользователя (ввод запросов и показ
результатов) и подсистему взаимодействия с системой Б, устойчивую к
временному выдергиванию сетевого кабеля. (В качестве последней может
выступать и SMTP)

Система Б получает от нескольких систем А запросы, передает их в 2-3 поисковые
м ашины (используйте любой их интерфейс), осуществляет кеширование
результатов и не допускает одновременных одинаковых запросов к поисковым
машинам. Получив первые 10 результатов от каждой машины (кроме зависшых по
тайм-ауту), она бъединяет их и передает в систему А.


С ситемой А все боле-менее ясно, можно реализовать ее с помощью TurboGears например.
Но как организовать систему Б? Как реализовать отправку поискового запроса и получение результата?

Спасибо :)

lrrr said...

dr-begemot> А в каком именно месте проблема? Поисковые машины -- это гугл/яху?

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

dr-begemot said...

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

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

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

lrrr said...

А, ну так тупо по хттп отправить запрос и парсить результаты.

Что касается отправить это http:request и то что вокруг.

Чтоб результаты парсить -- смотрите в сторону модулей regexp и, возможно, xmerl, если страница с выдачей является более-менее валидным xhtml.

lrrr said...

Прим.: но гугль, естественно, не будет рад куче запросов от ботов, чтоб его использовать в промышленных масштабах, придется с ним как-то договориться (вроде там API какой-то есть еще).

lrrr said...

Мега-простейший-тупой-учебный вариант без проверки чего бы то ни было и даже без urlencode(), то бишь работать будет только для запросов без пробелов и не-ASCII символов:

http://paste.defun.ru/m64f0ee8c

> c(goog).
> goog:start().
> goog:goog("bzz").

dr-begemot said...

То что надо :)
Спасибо огромное)))
как раз по институту и надо ;)

А где можно почитать о том как реализовать подсистему взаимодействия устойчивую к временному выдёргиванию сетевого кабеля (т.е. на smtp наверное)?

lrrr said...

Гм, не знаю где почитать, а SMTP не такой уж и устойчивый, он session-based таки. А вот HTTP как раз устойчивее некуда.

Еще в сторону всяких AMQP и XMPP можно поковырять, но я тут ничего толкового кроме самих аббревиатур не могу подсказать :)

dr-begemot said...

Здраствуйте)
Нужен еще один совет...

Как запустить несколько Erlang-узлов на одном компьютере?
Пытаюсь сделать так:
1. Запускаю 2 консоли Erlang.
2. В первой консоли прописываю комманду:
erl -sname node_1.
и получа ошибку:
* 1: syntax error before: node_1

В чем проблема?

Во 2й консоли хотел вбить
erl -sname node_2.
и потом запусить сервер из первой консоли, а клиента из 2й.
Или я чего-то не понял в запуске Erlang-узлов на одном ПК?

lrrr said...

dr-begemot> Не-не, надо сам эрланг с флажком -sname запускать

Anonymous said...

А по подробнее. У меня также: запускаю ерланг с ключем -sname _имя_, а мне выдает кучу ошибок:-( ...что делать? кто виноват?..

Panthera-IT said...

Думаю в вебсфере мало шансов будет. Только у кого root сервера и будут может быть пользоватся. Провайдеры небудут ставить это на сервера, покрайней мере ещё долгое время, если вообще. при том если учесть что такое зависит ещё от програм, которые устанавливаются на серверах Plesk, Confix, C-Panel и другие. Они незахотят встраивать это то же значит дополнительные разходы на разработку, а провайдерам которые этим пользуются, тоже сильно ненадо это, они ставят лунукс, или дебиан и чтонибудь для пользователей и всё.

А если подумать сколько проектов на других дб, зделанно и их переделывать, то просто нереально. Такие проекты как Drupal, Typo3, Wordpress и кучу других переделывать. Только новые проекты может и будут использовать новую базу.

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

Горбачёв said...

Во времена VDS-ов за 100 руб./мес мнение провайдеров по поводу используемых технологий уже никого не волнует.

Есть люди использующие Drupal и т.п., а есть другие - первые больше админы, вторые больше программеры:)

alekciy said...

>но CouchDb мне пинать пока жалко

Может по прошествии некоторого времени юзания ты его все же попинаешь, а?

lrrr said...

alekciy>
Пока нет, с тех пор его побольше поюзать не удалось :) Мы хотели на нем defun.ru делать, но там все заглохло.

Кстати сейчас может в одном проекте прикручу -- но пока не уверен что там лучше будет, couch или мускл.

максим said...
This comment has been removed by the author.
igrif said...

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

Albert Tovmasyan said...

Перезалейте картинки, пожалуйста!

Pre School Bangalore Indira Nagar said...

Your informational post is great resource to lots of peoples, because its having the useful message, so i would like to thank for creating this interesting blog...