понедельник, 10 ноября 2008 г.

О масштабируемости систем(ч.1)

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

Система считается масштабируемой, если ее производительность растет как минимум линейно в зависимости от увеличения производительности аппаратной части (увеличили количество серверов вдвое - производительность как минимум вдвое выросла). Чтобы добиться таких показателей, необходимо закладывать определенные архитектурные решения в проект с самого начала. Неправильно спроектированную систему в будущем будет крайне трудно, а то и просто невозможно масштабировать. Рассмотрим основные best-practices, которые мне известны на текущий момент.

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

Горизонтальное разбиение функциональности
Функциональная декомпозиция позволяет достичь определенного прогресса в масштабируемости, однако это далеко не все. Мы должны также иметь возможность разделять общую входящую нагрузку на функциональный блок системы и иметь возможность сбалансированно ее распределять между серверами пула. Для этого можно использовать стандартный load-balancer на уровне серверов приложений, который распределит нагрузку более-менее равномерно. Подразумевается, что каждый экземпляр сервера приложений содержит идентичную и автономную от других функциональность, так что можно просто увеличивать их количество в случае возросшей нагрузки. На уровне БД все обстоит несколько сложнее. Тут необходимо организовывать данные как т.н. "осколки" (shards). Это значит, что например, данные по пользователям равномерно распределены между N серверами БД, аждый из которых хранит свою часть. При этом есть механизм, который автоматически определяет, к какому серверу необходимо обратиться, чтобы получить нужные данные. Естесственно для сервреров приложений это должно быть совершенно прозрачно и они должны быть абстрагированы от деталей реализации. Есть специальные стратегии построения БД для такой конфигурации серверов, как правило, особым образом формируется первичный ключ таблицы, который идентифицирует, на каком сервере будет храниться запись. Хотя наверняка есть и другие варианты, я пока этим вопросом глубоко не занимался.

Комментариев нет: