Learning Platform
Глоссарий Troubleshooting
Урок 03.01 · 21 мин
Средний
mppshared-nothingarchitecturescalability

Massively Parallel Processing: модель shared-nothing

В первом модуле мы выяснили, что Trino — это распределённый SQL query engine, и не раз упоминали, что скорость на больших данных приходит из параллелизма. Пора разобрать, что именно стоит за словом «распределённый». Trino построен по архитектуре MPP — massively parallel processing — на основе модели shared-nothing. Этот урок открывает модуль про устройство кластера, и без него все следующие уроки — про координатор, воркеры, обмен данными — повисли бы в воздухе.

Понять MPP важно потому, что это фундаментальное архитектурное решение Trino. Из него вытекает всё: почему запрос на терабайт данных можно ускорить, просто добавив машин; почему узлы взаимозаменяемы; почему по умолчанию нет fault tolerance; почему кластер тянет сотни конкурентных пользователей. Если в голове есть точная модель MPP, остальное в курсе становится её следствиями.


Проблема: один компьютер не справляется

Начнём с задачи. Нужно выполнить аналитический запрос поверх таблицы на 1 ТБ: просканировать, отфильтровать, сгруппировать, посчитать агрегаты. Один компьютер, даже мощный, упирается здесь в физические пределы. Диск читает данные с ограниченной скоростью. Память конечна — терабайт в неё целиком не положить. Процессор обрабатывает строки с конечной скоростью. Запрос будет идти долго, и купить машину в десять раз быстрее нельзя — таких просто нет, рост производительности одной машины давно замедлился.

Есть два принципиально разных способа нарастить мощность вычислительной системы. Scale up (вертикальное масштабирование) — взять машину больше: больше ядер, больше памяти, более быстрый диск. У этого пути есть жёсткий потолок: самая мощная машина в мире всё равно одна и всё равно конечна. Scale out (горизонтальное масштабирование) — взять много обычных машин и заставить их работать над задачей вместе. У этого пути потолок несравнимо выше: машин можно поставить десять, сто, тысячу.

Два пути масштабирования
Scale upВертикальное масштабирование: одна машина побольше — больше ядер и памяти. Жёсткий физический потолок
Trino выбирает
Scale outГоризонтальное масштабирование: много обычных машин работают над задачей вместе. Потолок несравнимо выше

Trino выбирает scale out. И MPP — это и есть архитектура, которая позволяет много обычных машин превратить в один мощный движок запросов.

Что такое MPP

MPP, massively parallel processing — массово-параллельная обработка — это архитектура, в которой одна задача (запрос) разбивается на множество мелких независимых частей, и эти части исполняются параллельно на множестве узлов кластера.

Слово «massively» здесь не для красоты. Речь не о паре потоков, а о массовом параллелизме: запрос на терабайт может породить тысячи мелких единиц работы, разложенных по десяткам узлов, и на каждом узле — ещё на множество параллельных потоков. Параллелизм идёт сразу на двух уровнях: между узлами кластера и внутри каждого узла между его ядрами.

Логика проста и мощна. Если просканировать 1 ТБ на одной машине занимает, условно, 100 минут, то на 100 машинах, каждая из которых обрабатывает свои 10 ГБ, та же работа в идеале займёт около 1 минуты. Запрос ускоряется примерно во столько раз, во сколько вырос кластер. Это и есть обещание MPP: производительность растёт почти линейно с числом узлов.

MPP: запрос разбивается на параллельные части
Один запрос на 1 ТБАналитический запрос поверх большой таблицы — слишком тяжёлый для одной машины
разбивается на части
Узел 1Обрабатывает свой кусок данных независимо от других узлов, параллельно с ними
Узел 2Обрабатывает свой кусок данных, не пересекаясь с узлом 1
Узел 3Обрабатывает свой кусок данных, не пересекаясь с узлами 1 и 2
результаты собираются вместе
Итоговый результатЧастичные результаты узлов объединяются в финальный ответ запроса

Это «оговорённое почти». Линейное ускорение — идеал, к которому MPP стремится, но не всегда достигает: часть работы требует обмена данными между узлами, и этот обмен (network exchange) — тема следующих уроков модуля. Но как ориентир: добавил вдвое больше узлов — получил примерно вдвое быстрее, и это работает на удивление хорошо.

Модель shared-nothing

MPP можно строить по-разному. Trino строит его по модели shared-nothing — «ничего не общего». Это означает: узлы кластера не делят между собой никаких ресурсов. У каждого узла свой процессор, своя оперативная память, свой локальный диск, и узел работает только с ними. Узлы не пишут в общую память и не используют общий диск; единственный способ их взаимодействия — обмен сообщениями по сети.

Противоположность — модели shared: shared-memory (узлы делят общую память) и shared-disk (узлы делят общее хранилище). У этих моделей есть фундаментальная проблема: общий ресурс становится узким местом и точкой конкуренции. Когда сто узлов одновременно лезут в одну память или на один диск, им приходится координировать доступ, выстраиваться в очередь, синхронизироваться. Чем больше узлов, тем сильнее давка вокруг общего ресурса, и масштабирование упирается в потолок.

В shared-nothing этой проблемы нет по построению. Раз общего ресурса нет, нет и давки за него. Каждый узел полностью автономен: получил свой кусок данных — обработал на своём железе — отдал результат. Добавить узел — значит добавить полный комплект независимых ресурсов: ещё один процессор, ещё одну память, ещё один диск. Именно поэтому shared-nothing масштабируется почти линейно, а shared-модели — нет.

Shared-nothing: у каждого узла свои ресурсы
Узел 1Свой CPU, своя память, свой локальный диск — полностью автономен, ничего не делит с другими
Узел 2Свой CPU, своя память, свой локальный диск — полностью автономен
Узел 3Свой CPU, своя память, свой локальный диск — полностью автономен
АспектShared-memory / shared-diskShared-nothing (Trino)
Общий ресурсПамять или диск делятся всеми узламиНичего общего, каждому узлу — свой комплект
Узкое местоКонкуренция за общий ресурсНет общего ресурса — нет конкуренции
МасштабированиеУпирается в потолок при росте узловПочти линейное при добавлении узлов
Взаимодействие узловЧерез общий ресурсТолько обмен сообщениями по сети
Spark: Driver и Executor — модель распределённых вычислений ClickHouse: стратегии шардирования
NOTE

Shared-nothing — не изобретение Trino. По этой модели построены практически все современные распределённые аналитические системы: Spark, аналитические MPP-хранилища, многие облачные движки. Термин ввёл ещё в 1986 году Майкл Стоунбрейкер. Trino — чистая и современная реализация этой давно проверенной идеи.

Что shared-nothing даёт Trino

Из выбора shared-nothing-MPP вытекают сразу несколько ключевых свойств Trino, которые мы будем разбирать дальше в курсе.

Горизонтальная масштабируемость. Не хватает мощности — добавляете воркеров. Каждый новый воркер — это полный комплект независимых ресурсов, и кластер становится быстрее почти линейно. Стало меньше нагрузки — убираете воркеров. Это эластичность, которой нет у одной машины.

Взаимозаменяемость узлов. Раз узлы автономны и не хранят ничего уникального, они одинаковы и заменяемы. Любой воркер может взять любой кусок работы. Это сильно упрощает эксплуатацию: добавление и вывод узлов — рутинная операция, а не перестройка системы.

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

Но у медали есть и обратная сторона, и честный разбор требует её назвать. Поскольку узлы автономны и держат промежуточные данные запроса только в своей оперативной памяти, выход узла из строя посреди запроса означает потерю его части работы. По умолчанию это приводит к падению всего запроса — отсюда отсутствие fault tolerance, о котором мы уже упоминали. Это прямое следствие модели, и ему посвящён последний урок модуля.

Где у MPP пределы

Чтобы не идеализировать, обозначим границы. MPP не делает любой запрос быстрее в N раз на N узлах. Линейность нарушается, когда задача требует, чтобы данные с разных узлов встретились друг с другом — например, при джойне или глобальной агрегации. Тогда узлам приходится перераспределять данные между собой по сети, а сеть медленнее локальной памяти и сама может стать узким местом. Кроме того, у любого запроса есть часть, которую невозможно распараллелить (скажем, финальная сборка единого результата), и эта часть ограничивает максимальное ускорение. Trino спроектирован так, чтобы минимизировать сетевой обмен и неделимые участки — как именно, мы разберём в уроках про exchange и про распределённое исполнение. Пока достаточно понимать: MPP даёт огромный, но не бесконечный и не идеально линейный выигрыш.

Попробуй сам

Возьмите конкретную задачу: просканировать таблицу на 2 ТБ и посчитать count(*) с фильтром. Прикиньте на бумаге, сколько времени это займёт на 1 узле, на 10 узлах и на 100 узлах, если один узел обрабатывает данные со скоростью, условно, 1 ГБ за 5 секунд. Запишите три числа и убедитесь, что видите линейный характер ускорения.

Затем подумайте над вторым вопросом: что изменится, если запрос — не просто count, а джойн двух больших таблиц, и данным с разных узлов нужно встретиться по ключу джойна. Почему здесь идеальная линейность нарушится? Сформулируйте письменно своими словами, какой именно ресурс становится узким местом — это подготовит вас к уроку про exchange.


Проверка знанийKnowledge check
Что такое MPP и модель shared-nothing, и почему именно shared-nothing даёт Trino почти линейную масштабируемость?
ОтветAnswer
MPP (massively parallel processing) — это архитектура, в которой одна задача (запрос) разбивается на множество мелких независимых частей, и они исполняются параллельно на множестве узлов кластера и на множестве ядер внутри каждого узла. Логика проста: если на одной машине запрос идёт 100 минут, то на 100 машинах, каждая из которых обрабатывает свой кусок, та же работа в идеале займёт около минуты — производительность растёт почти линейно с числом узлов. Trino строит MPP по модели shared-nothing: узлы не делят между собой никаких ресурсов, у каждого свой процессор, своя оперативная память, свой локальный диск, а единственный способ взаимодействия — обмен сообщениями по сети. Это и есть причина почти линейной масштабируемости. В моделях shared-memory и shared-disk узлы делят общий ресурс, и при росте числа узлов он становится узким местом и точкой конкуренции: узлам приходится выстраиваться в очередь за доступом. В shared-nothing общего ресурса нет по построению, поэтому нет и давки за него: каждый узел полностью автономен, а добавление узла — это добавление полного комплекта независимых ресурсов. Поэтому добавление узлов почти линейно ускоряет кластер. Цена модели — узлы держат промежуточные данные только в своей памяти, и выход узла из строя по умолчанию роняет весь запрос (отсутствие fault tolerance).

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 4. Что означает MPP (massively parallel processing) в архитектуре Trino?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 6