Как стать автором
Обновить

Комментарии 38

спасибо за статью и ссылки, особенно про postgresql
Репликация — это не совсем решение, а если речь идет не о единицах серверов, а о хотя бы десятках — вообще не решение.

Более того, то, что шардинг в NoSQL сильно проще, чем в РСУБД, это несколько не соответствует действительности. Чисто технически — почти одинаково. Дело в другом: при работе с РСУБД надо перестраивать мозг, а на key-value все «ложится» практически сразу и само.
Полезно. Обзорно.
Спасибо. Всегда хотел знать, как же такие штуки устроены.
Каждый High-load разный.

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

Общий подход, мне кажется, вполне одинаковый.
Согласен, что вся соль именно в деталях, но целью данной статьи был именно поверхностный обзор. Каждая приведённая выше веха по хорошему заслуживает отдельной статьи.
Отличная статья. Продолжение будет?
Секционирование есть и в mysql начиная с 5.1
Есть, да не совсем. Отсекционируйте-ка мне этим секционированием табличку на 5 000 000 000 записей по сотенке серверов ;)
А в чем проблема собственно?
Ну а как вы себе это представляете?
Вообще-то эта задча решается скорее клиентской библиотекой, чем СУБД.
Один вопрос, на который я не могу найти ответ:

как при шардинге базы добавляются новые сервера в кластер базы?
Если например у нас есть 3 сервера (3 базы), то при добавлении 4-го нам ведь надо все данные
с этих трех переворошить и распределить на 4 части (по новой хеш функции),
а это совсем нетривиальная задача при миллионах записей.

Не надо ничего ворошить ;)

Шардится всё всегда по какому-то сиквенсу, например user_id — вот и хранится карта соответствий

[ { user_id_range1 => server_id_1 }, { user_id_range2 => server_id_2 },… ]

Ее несложно сделать общедоступной: любой самый простейший key value сервер, либо просто разложить на все аппликейшен-ноды конфиг — не так уж это и часто надо.
Не всё так просто на самом деле. Шардить приходится по разным критериям, далеко не всегда есть смысл делать «первый миллион идёт на сервер1, второй на сервер2 и т.д.». Иногда приходится шардить по странам, иногда по именам. А потом оказывается что Джонов гораздо больше чем Зоуи, и на шард J-L нужно добавить ещё серверов. И решардинга не избежать.
По сути это не такая уж и страшная операция, если её делать вовремя. Никто не держит сервера загруженными на 100%, всегда должен быть запас ресурсов, которые можно отдать под решардинг. На старых серверах немного возрастает чтение, на новых соответственно запись. Но если проспать нужный момент (как например произошло с Foursquare), тогда действительно проблем не избежать.
Не спорю, кейсы бывают разные, но в целом, если рассматривать не конкретный кейс, а среднее по больнице, я против такой архитектуры, когда на шарды завязана какая-то там логика, искусственно вводимая для избежания кросс-шард запросов, это очень сложно суппортить и чревато неожиданностями. Проще создать внешние индексы в какой-то шустрой искалке, типа sphinx RT, а шарды воспринимать как key-value, которые вне рамок PK просто ничего не умеют. Стоимость дисков возрастает линейно, а стоимость суппорта таких выкрутасов растет в лучшем случае геометрически =)
И да, я читал доклад по архитектуре 4sq, это ж убиться веником. Сами себе проблемы придумали.
Ну вариант с диапазонами id понятен ( просто с какого то момента все новые пользователи
отправляются на новые сервера). Но в этом случае уже не будет равномерного красивого распределения данных. Или это нормальная практика?
Дык тут все просто — на первых серверах экспериментально определяем, сколько разумно засунуть на один сервер (заранее все равно не угадаешь характер нагрузки, распределение популярности и активности), тут можно и мелкими диапазонами. А дальше уже знаем сколько выделять. Учитывая что на одном сервере пользователей все равно получится дофига, будет примерно равномерно :)
Ну и кстати надо заметить, что шардить может оказаться полезным не только по серверам, но и по таблицам (тут профит очевиден; можно заюзать тот же встроенный партишенинг, а можно и не заюзать =)), и даже по базам/схемам (зависит от конкретной СУБД и специфики ее реализации).
У нас postgres, сейчас 8 баз на 4 серверах с запасом в 3-4 раза.
Кластеризацию осуществляем через plproxy, делим данные по user_id равномерно.
В нагруженных таблицах где то по 20-40 мл записей.
Оптимистично мы ожидаем прирост пользователей через год на 200-500%.

Узким местом оказался plproxy, который помимо проблем с производительностью
добавил огромные сложности в разработке.

Сейчас избавляемся от plproxy, переводя всю логику в основной код (java)
Также рассматриваем частичный переход на noSQL

partitioning к сожалению в postgresql крайне зачаточный, не в пример mysql 5.5, там все гораздо удобнее. Успешно использую данный механизм оптимизации в своем приложении, работает :)
Использую partitioning (postgres 8.4) для таблицы в 50 млн. записей. Кроме необходимости ручного создания новых таблиц никаких затруднений не ощущаю.
А наследование индексов в наследуемых таблицах там сделали? Или до сих пор ручками? Помню, что было в TODO давно еще…
На 9.0 индексы для наследуемых таблиц приходится создавать, к сожалению, явно. Тем не менее, с учётом того, что создание дочерний таблицы легко оборачивается в функцию, — это не большая проблема.
Вот это я и имел ввиду, когда говорил, что в mysql удобнее, в postgresql все ручками нужно делать.
НЛО прилетело и опубликовало эту надпись здесь
Я, честно говоря, вообще считаю, что кластерные ФС это вынужденная мера, когда какому-то уже написанному приложению надо подсунуть нечто, о чем оно будет думать, как о локальной posix FS. Как и вообще считаю, что любой кластер (в полноценном понимании слова) это такой workaround, чтобы смасштабировать немасштабируемое.

А если заранее делаем, грубо говоря, фейсбук, а не страничку Васи Пупкина, которая ВНЕЗАПНО стала превращаться в фейсбук, разумно все предусмотреть на уровне приложения. С точки зрения производительности — никогда не будет ничего быстрее тупой отдачи файла с обычной фс обычного диска, с точки зрения управляемости — на апплевеле всегда более управляемо.

Для типичных вебдванольных задач (фоточки-видюшки) решается все очень просто, пара классов по сотне строк на любимом скриптовом ЯП.
НЛО прилетело и опубликовало эту надпись здесь
Ваша правда. Но когда таки пошло, разумно, поддерживая костылями что есть, параллельно начинать делать по уму и разрабатывать план миграции. Иначе есть немалый риск, что стоимость владения будет прогрессировать с каждым новым пользователем и с каждой новой фичей до бесконечности.
«Кроме того, этот подход (вертикальное масштабирование) не требует никаких доработок приложения.»
Строго говоря это не всегда так. Хорошо вертикально масштабируются только или компоненты в которых нет конкурентного доступа к разделяемым ресурсам (типа нитей выполнения php/perl/вашлюбимыйсерверныйязык) либо достаточно простые вещи.
Сложные части вроде СУБД могут плохо масштабироваться вертикально. Особенно если преобладает write-нагрузка. Увеличение количества ядер и памяти сервера с некоторого момента не оказывает влияния.
И гораздо разумней этот многоядерный многогигабайтный сервер нарезать на виртуальные машинки по 2-4 ядра (в зависимости от того что туда хотите ставить) и делать необходимые доработки в архитектуре для переходя к горизонтальному масштабированию (пусть и внутри пока одного физического сервера)

Ещё в копилку ключевых слов:
Механизм с поднятием нескольких экземпляров одной базы на разных серверах, master/slave репликацией и распределением операций записи на master, чтений на slave'ы — называется read/write split — и работает опять же только если у нас преобладает read-нагрузка. И имеет очевидное ограничение до которого так можно масштабироваться — количество запросов на изменение данных которое может переварить 1 сервер.
Спасибо за статью. В избранное.
lethargy.org/~jesus/writes/partitioning-vs.-federation-vs.-sharding
Упс, промазал :)
Файлы статики можно смонтировать с некого общего файлового хранилища по NFS/CIFS или использовать распределённую ФС (HDFS, GlusterFS, Ceph).
глупее совета не встречал.
Если у Вас нагруженная система то ваша NFS гавкать будет, как резанный кролик. Если вы хотите сделать распределенное хранилище файлов — то почитайте что такое шардинг. Обычный шардинг контента на несколько серверов. Задача не сложнее шардинга БД, кстати про который здесь было упомянуто как-то вскользь. Поспрашивайте у ребят из Мамбы, Баду или Сонетика — как все это сделать.
Отдельно стоит отметить проблему деплоймента на несколько хостов. Как сделать так, что бы пользователь, нажимая «Обновить», не видел разные версии приложения? Самым простым решением, на мой взгляд, будет исключение из конфига балансировщика нагрузки (web-сервера) не обновлённых хостов, и последовательного их включения по мере обновления. Так же можно привязать пользователей к конкретным хостам по cookie или IP. Если же обновление требует значимых изменений в БД, проще всего, вообще временно закрыть проект.
все решается тривиально просто:
есть конфиг версий, есть index.php который подгружает классы из соответствующей папки: папка — номер ревизии свн.
есь скрипт, который одновременно заливает на n серверов новый конфиг.
Как только мы развернули на n серверах новую версию в нужной папочке — используя scp/tar а не svn co
мы запускаем скрипт инициализации, который модифицирует БД, и после чеего производит централизованное переключение верси.
Всегда просто сделать Откат, запустив скрипт, который лишь изменит (на всех серверах одновременно) одну строчечку номера версии на предыдущую.
все как дважды два!!!
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории