Тарифы Услуги Сим-карты

Масштабирование нагрузки web-приложений. Модель с применением множества доверенных удостоверений сервиса

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

В системе с плохой масштабируемостью добавление ресурсов приводит лишь к незначительному повышению производительности, а с некоторого «порогового» момента добавление ресурсов не даёт никакого полезного эффекта.

Вертикальное масштабирование

Увеличение производительности каждого компонента системы c целью повышения общей производительности.

Горизонтальное масштабирование

Разбиение системы на более мелкие структурные компоненты и разнесение их по отдельным физическим машинам (или их группам) и/или увеличение количества серверов параллельно выполняющих одну и ту же функцию.

Примечания

См. также

Ссылки


Wikimedia Foundation . 2010 .

Смотреть что такое "Масштабируемость" в других словарях:

    масштабируемость - расширяемость Характеристика приложения, которое исполняется на разных платформах и варьируется в размерах (например, на PC под Windows и на рабочей станции Sun под Unix). Для аппаратных средств предсказуемый рост системных характеристик при… …

    масштабируемость - 3.1.43 масштабируемость (scalability): Способность обеспечивать функциональные возможности вверх и вниз по упорядоченному ряду прикладных платформ, отличающихся по быстродействию и ресурсам. Источник … Словарь-справочник терминов нормативно-технической документации

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

    масштабируемость системы (в SCADA) - масштабируемость системы [Интент] Масштабируемость системы. Это означает, что разработанный проект можно опробовать на одном компьютере или маленькой сети и затем расширять систему (в соответствии с программой развития, бюджетом и т. д.) без… … Справочник технического переводчика

    масштабируемость (в информационных технологиях) - Способность ИТ услуги, процесса, конфигурационной единицы и т.п., выполнять свою ранее согласованную функцию, в случае изменения рабочей нагрузки или охвата. [Словарь терминов ITIL версия 1.0, 29 июля 2011 г.] EN scalability The ability of an IT… … Справочник технического переводчика

    масштабируемость (приложения) - масштабируемость расширяемость Характеристика приложения, которое исполняется на разных платформах и варьируется в размерах (например, на PC под Windows и на рабочей станции Sun под Unix). Для аппаратных средств предсказуемый рост системных… … Справочник технического переводчика

    масштабируемость (сети и системы связи) - Критерий экономически эффективной системы автоматизации подстанции, учитывающий различные функциональные характеристики, различные интеллектуальные электронные устройства, размер подстанции и диапазоны напряжений подстанции. [ГОСТ Р 54325 2011… … Справочник технического переводчика

    масштабируемость в широких пределах - — [Л.Г.Суменко. Англо русский словарь по информационным технологиям. М.: ГП ЦНИИС, 2003.] Тематики информационные технологии в целом EN terabyte scalability … Справочник технического переводчика

    горизонтальная масштабируемость - Наращивание мощности системы добавлением узлов в кластер. Тематики информационные технологии в целом EN horizontal scalability … Справочник технического переводчика

    SCALABILITY - масштабируемость - один из основных принципов построения открытых систем, гарантирует сохранение инвестиций в информацию и ПО при переходе на более мощную аппаратную платформу … Словарь электронного бизнеса

Книги

  • Microsoft SharePoint 2010. Полное руководство , Майкл Ноэл, Колин Спенс. В книге рассматриваются все новые возможности SharePoint - от новых компонентов социальных сетей до усовершенствованного поиска - которые помогают максимально задействовать как SharePoint…

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

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

Вертикальное масштабирование подразумевает увеличение мощности отдельного сервера СУБД и достигается заменой аппаратного обеспечения (процессора, дисков) на более быстродействующее или добавлением дополнительных узлов. Хорошим примером может служить увеличение числа процессоров в симметричных многопроцессорных (SMP) платформах. При этом программное обеспечение сервера не должно изменяться (в частности, нельзя требовать закупки дополнительных модулей), так как это увеличило бы сложность администрирования и ухудшило предсказуемость поведения системы. Независимо от того, какой способ масштабирования использован, выигрыш определяется тем, насколько полно программы сервера используют доступные вычислительные ресурсы. В дальнейших оценках мы будем рассматривать вертикальное масштабирование, испытывающее, по мнению аналитиков, наибольший рост на современном компьютерном рынке.

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

  • поддержка многопроцессорной обработки;
  • гибкость архитектуры.

Многопроцессорные системы

Для вертикального масштабирования все чаще используются симметричные многопроцессорные системы (SMP), поскольку в этом случае не требуется смены платформы, т.е. операционной системы, аппаратного обеспечения, а также навыков администрирования. С этой целью возможно также применение систем с массовым параллелизмом (MPP), но пока их использование ограничивается специальными задачами, например, расчетными. При оценке сервера СУБД с параллельной архитектурой целесообразно обратить внимание на две основные характеристики расширяемости архитектуры: адекватности и прозрачности.

Свойство адекватности требует, чтобы архитектура сервера равно поддерживала один или десять процессоров без переустановки или существенных изменений в конфигурации, а также дополнительных программных модулей. Такая архитектура будет одинаково полезна и эффективна и в однопроцессорной системе, и, по мере роста сложности решаемых задач, на нескольких или даже на множестве (MPP) процессоров. В общем случае потребитель не должен дополнительно покупать и осваивать новые опции программного обеспечения.

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

Качественная поддержка многопроцессорной обработки требует от сервера баз данных способности самостоятельно планировать выполнение множества обслуживаемых запросов, что обеспечило бы наиболее полное разделение доступных вычислительных ресурсов между задачами сервера. Запросы могут обрабатываться последовательно несколькими задачами или разделяться на подзадачи, которые, в свою очередь, могут быть выполнены параллельно (рис. 3). Последнее более оптимально, поскольку правильная реализация этого механизма обеспечивает выгоды, независимые от типов запросов и приложений. На эффективность обработки огромное воздействие оказывает уровень гранулярности рассматриваемых задачей-планировщиком операций. При грубой гранулярности, например, на уровне отдельных SQL-запросов, разделение ресурсов вычислительной системы (процессоров, памяти, дисков) не будет оптимальным - задача будет простаивать, ожидая окончания необходимых для завершения SQL-запроса операций ввода/вывода, хотя бы в очереди к ней стояли другие запросы, требующие значительной вычислительной работы. При более тонкой гранулярности разделение ресурсов происходит даже внутри одного SQL-запроса, что еще нагляднее проявляется при параллельной обработке нескольких запросов. Применение планировщика обеспечивает привлечение больших ресурсов системы к решению собственно задач обслуживания базы данных и минимизирует простои.

Гибкость архитектуры

Независимо от степени мобильности, поддержки стандартов, параллелизма и других полезных качеств, производительность СУБД, имеющей ощутимые встроенные архитектурные ограничения, не может наращиваться свободно. Наличие документированных или практических ограничений на число и размеры объектов базы данных и буферов памяти, количество одновременных подключений, на глубину рекурсии вызова процедур и подчиненных запросов (subqueries) или срабатывания триггеров базы данных является таким же ограничением применимости СУБД как, например, невозможность переноса на несколько вычислительных платформ. Параметры, ограничивающие сложность запросов к базе данных, в особенности размеры динамических буферов и стека для рекурсивных вызовов, должны настраиваться в динамике и не требовать остановки системы для реконфигурации. Нет смысла покупать новый мощный сервер, если ожидания не могут быть удовлетворены из-за внутренних ограничений СУБД.

Обычно узким местом является невозможность динамической подстройки характеристик программ сервера баз данных. Способность на ходу определять такие параметры, как объем потребляемой памяти, число занятых процессоров, количество параллельных потоков выполнения заданий (будь то настоящие потоки (threads), процессы операционной системы или виртуальные процессоры) и количество фрагментов таблиц и индексов баз данных, а также их распределение по физическим дискам БЕЗ останова и перезапуска системы является требованием, вытекающим из сути современных приложений. В идеальном варианте каждый из этих параметров можно было бы изменить динамически в заданных для конкретного пользователя пределах.

Олег Спиряев

В последнее время нередки утверждения, что серверы среднего и старшего класса активно заменяются на группы серверов начального уровня, объединенные в стойки или кластеры. Однако некоторые эксперты с этим не согласны. Так, по данным Dataquest, доля моделей ценой от 500 тыс. долл. и выше (к ним относятся средние и старшие серверы SMP) в общем объеме продаж серверов с 2000 до 2002 г. выросла с 38 до 52%.

Другие данные, полученные компанией IDC, свидетельствуют о росте (по крайней мере, по числу машин) в секторе младших моделей серверов - с двумя процессорами. IDC также предсказывает, что в 2005 г. самой распространенной операционной системой для серверов стоимостью от 50 тыс. до 3 млн долл. будет Unix. Из сравнения этих данных видно, что Unix-серверы среднего и старшего класса останутся преобладающей платформой для центров обработки данных, но будут дополняться все растущим числом небольших (обычно двухпроцессорных) серверов.

Эта тенденция сложилась в результате выделения в центрах обработки данных разных уровней вычислений (рис. 1). Уровень 1, или фронтальный уровень, постепенно переходит на модель горизонтального масштабирования небольших серверов, а на уровне 3 (уровне баз данных) преобладают серверы с вертикальным масштабированием. Уровень 2 (уровень приложений) становится областью, где сосуществуют вертикальная и горизонтальная архитектуры.

Вертикальная и горизонтальная архитектуры

Рассмотрим основные различия между вертикальной и горизонтальной архитектурами. Серверы с вертикальным масштабированием - это большие SMP-системы (с симметричной многопроцессорной обработкой или совместно используемой памятью), насчитывающие свыше четырех центральных процессоров. В них используется только одна копия ОС, управляющая работой всех процессоров, памяти и компонентов ввода-вывода. Обычно все эти ресурсы размещены в одной стойке или шкафу. Межсоединения у таких серверов осуществляются по высокоскоростной центральной или объединительной панели с небольшим временем запаздывания и согласованным доступом к кэш-памяти. Добавить ресурсы можно путем установки внутрь шкафа дополнительных системных плат. В системах с вертикальной архитектурой (или SMP-системах) память используется совместно, т. е. все процессоры и компоненты ввода-вывода получают доступ ко всей памяти. Пользователь "видит" память как единый большой объект.

При альтернативном, горизонтальном масштабировании системы соединяются через сеть или объединяются в кластер. Для межсоединений обычно используются стандартные сетевые технологии, такие, как Fast Ethernet, Gigabit Ethernet (GBE) и Scalable Coherent Interconnect (SCI), дающие меньшую пропускную способность и большее запаздывание по сравнению с вертикальными системами. Ресурсы в этом случае распределяются между узлами, обычно содержащими от одного до четырех процессоров; каждый узел имеет собственный процессор и память и может иметь собственную подсистему ввода-вывода или использовать ее совместно с другими узлами. На каждом узле работает отдельная копия ОС. Ресурсы расширяются за счет добавления узлов, но не добавления ресурсов в узел. Память в горизонтальных системах распределена, т. е. у каждого узла есть собственная память, к которой напрямую обращаются его процессоры и подсистема ввода-вывода. Доступ к этим ресурсам с другого узла происходит намного медленнее, чем с узла, где они расположены. Кроме того, при горизонтальной архитектуре отсутствует согласованный доступ узлов к памяти, а используемые приложения потребляют относительно немного ресурсов, поэтому они "умещаются" на одном узле и им не нужен согласованный доступ. Если же приложению потребуется несколько узлов, то оно само должно обеспечить согласованный доступ к памяти.

Если горизонтальная система удовлетворяет требованиям приложений, то такая архитектура предпочтительна, поскольку расходы на ее приобретение меньше. Обычно стоимость приобретения в расчете на один процессор у горизонтальных систем ниже, чем у вертикальных. Разница в цене объясняется тем, что в вертикальных системах применяются более мощные функции надежности, доступности и обслуживаемости - RAS (reliability, availability, serviceability), а также высокопроизводительные межсоединения. Однако есть ряд ограничений на применение систем с горизонтальной архитектурой. Ниже мы обсудим, в каких условиях возможно применение горизонтальных систем и когда обязательно вертикальное масштабирование.

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

Недавно появившиеся на рынке модульные, или blade-серверы, обычно оборудуемые одним-двумя процессорами, - пример горизонтальных серверов. Здесь кластер состоит из небольших узлов, в каждом из которых установлен SMP-сервер начального уровня с числом центральных процессоров от 1 до 4.

Другой способ горизонтального масштабирования - это большие вычислительные системы с массовым параллелизмом (MPP), состоящие из множества установленных в одном шкафу небольших процессоров, каждый из которых имеет собственную копию ОС или копию микроядра ОС. В настоящее время выпускаются всего несколько систем MPP, которые чаще всего представляют специализированные решения. Это, например, системы Terradata производства компании NCR, IBM RS/6000SP (SP-2) и HP Tandem non-stop.

Таблица 1. Особенности вертикальной и горизонтальной архитектур

Параметр Вертикальные системы Горизонтальные системы
Память Большая совместно используемая Небольшая выделенная
Потоки Много взаимозависимых потоков Много независимых потоков
Межсоединения Сильносвязанные внутренние Слабосвязанные внешние
RAS Мощные RAS одиночной системы Мощные RAS с использованием репликации
Центральные процессоры Много стандартных Много стандартных
ОС Одна копия ОС на множество центральных процессоров Несколько копий ОС (по одной копии на 1-4 процессора)
Компоновка В одном шкафу Размещение большого числа серверов в стойке
Плотность размещения Высокая плотность размещения процессоров на единицу площади пола
Оборудование Стандартное и специально разработанное Стандартное
Масштабирование В пределах корпуса одного сервера В масштабе нескольких серверов
Расширение Путем установки в сервер дополнительных компонентов Путем добавления новых узлов
Архитектура 64-разрядная 32- и 64-разрядная

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

  • В вертикальных системах память используется совместно и обеспечивается согласованный доступ к кэш-памяти.
  • Вертикальные системы идеальны для потоков выполнения задач, которые должны обмениваться данными между собой.
  • Вертикальные системы характеризуются мощными функциями RAS, а в горизонтальных системах доступность реализуется с помощью массивной репликации (в кластер соединяются несколько узлов, поэтому отказ одного из них мало влияет на работу всей системы).
  • В вертикальных системах одна копия ОС охватывает все ресурсы. Некоторые вертикальные системы, например, мидфреймы и серверы класса high-end Sun Microsystems (от Sun Fire 4800 до Sun Fire 15K), можно разделить на меньшие вертикальные серверы.
  • В вертикальных системах используется максимально возможное число стандартных компонентов, но некоторые основные составляющие (например, межсоединения) специально разрабатываются.
  • Вертикальные системы можно расширять, устанавливая в существующий каркас дополнительные компоненты (более мощные процессоры, добавочную память, дополнительные и более производительные соединения ввода-вывода и т. п.). Горизонтальные системы расширяются за счет добавления узла или замены старых узлов на новые.
  • Практически все вертикальные системы 64-разрядные, а горизонтальные могут быть как 32-разрядными, так и 64-разрядными.

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

Таблица 2. Типы приложений для вертикальной и горизонтальной архитектур

Для небольших и модульных серверов хорошо подходят приложения, которые не используют информацию о состоянии, невелики по масштабу и легко реплицируются. А для приложений, использующих информацию о состоянии и большие объемы данных, требующих интенсивной передачи данных внутри системы, идеальным решением будут вертикальные серверы. На рынке высокопроизводительных технических вычислений (HPTC) имеется множество приложений, в которых потоки зависят друг от друга и обмениваются данными между собой. Существуют также приложения, которым нужны большие объемы совместно используемой памяти. Для этих двух типов приложений лучше всего подходят большие SMP-серверы. Однако имеются и такие приложения HPTC, в которых потоки исполнения независимы и им не требуется совместно используемая память большого объема. Такие приложения можно разбивать на разделы, и потому для их выполнения идеальны кластеры небольших серверов. Аналогичным образом некоторые коммерческие приложения поддерживают разделы, и для них оптимальны горизонтальные серверы, а другие нельзя разбить на разделы, поэтому для них лучшая платформа - это вертикальные серверы.

Факторы, влияющие на производительность

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

Процессоры и системные межсоединения

Процессоры, безусловно, существенный компонент, но они только отчасти определяют общую производительность системы. Более важно обеспечить работу процессоров с максимальной загрузкой. У мощного процессора, загруженного лишь на 50%, производительность будет хуже, чем у более медленного процессора, который загружен на 80%.

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

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

Основное техническое различие между горизонтальными и вертикальными системами - это пропускная способность и запаздывание их межсоединений. У межсоединений кластеров пропускная способность может составлять от 125 Мбайт/с для Fast Ethernet до 200 Мбайт/с для SCI, а запаздывание - от 100 тыс. нс для GBE и до 10 тыс. нс для SCI. С помощью интерфейса InfiniBand возможно реализовать более быстрые межсоединения с пиковой скоростью от примерно 250 Мбайт/с для первой версии и до 3 Гбайт/с для последующих.

Ввод и вывод

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

Операционная система

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

Доступность системы

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

Оптимизированные приложения

Приложения необходимо оптимизировать для архитектуры вычислительной системы. Легче всего писать и оптимизировать приложения для SMP-систем. Основные коммерческие приложения оптимизированы именно для SMP-систем и даже разрабатывались на них, поэтому SMP доминируют на рынке систем среднего класса и high-end последние десять лет.

Размер приложений

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

Например, в случае горизонтальной архитектуры (или архитектуры с распределенной памятью) четыре процессорных узла (каждый с отдельным ОЗУ и выделенной либо используемой совместно подсистемой ввода-вывода) могут использовать сетевое межсоединение, например, Gigabit Ethernet. В этой вычислительной среде выполняются рабочие нагрузки трех типов. Самая маленькая нагрузка помещается на одном узле, но по мере ее увеличения для выполнения требуется уже несколько узлов. Как утверждают специалисты, при выполнении одной задачи на нескольких узлах производительность значительно ухудшается из-за медленных межузловых межсоединений. Небольшие нагрузки, которым не нужно обмениваться данными между собой, прекрасно сочетаются с горизонтальной архитектурой, но при выполнении в ней крупномасштабных нагрузок возникают проблемы.

Конфигурация большой системы SMP может включать, например, до 100 процессоров, 576 Гбайт совместно используемой памяти и высокоскоростные межсоединения. Такая система может обрабатывать все типы нагрузок, поскольку в ней отсутствует обмен данными между узлами и эффективно осуществляется обмен данными между процессами. Все центральные процессоры могут одновременно получить доступ ко всем дискам, всей памяти и сетевым соединениям - это ключевая особенность SMP-систем (или вертикальных систем).

Часто возникает вопрос о целесообразности размещения на больших SMP малых нагрузок. Хотя в техническом плане это возможно, с экономической точки зрения такой подход себя не оправдывает. Для больших SMP стоимость приобретения в расчете на один процессор выше, чем для маленьких систем. Поэтому если приложение может работать на небольшом узле (или нескольких небольших узлах) и это не создает серьезных проблем с управлением, для его развертывания лучше подходит горизонтальное масштабирование. Но если приложение слишком велико и не может выполняться на небольшом узле (или нескольких таких узлах), то крупный SMP-сервер будет оптимальным вариантом с точки зрения как производительности, так и системного администрирования.

Производительность на уровне базы данных

Основной вопрос здесь - сравнение производительности одиночных средних и больших SMP-серверов с кластером небольших серверов (не более четырех процессоров).

При обсуждении масштабируемости фирмы-производители используют ряд специальных терминов. Так, рост производительности (Speedup) для SMP определяется как отношение скоростей выполнения приложения на нескольких процессорах и на одном. Линейный рост производительности (Linear speedup) означает, например, что на 40 процессорах приложение работает в 40 раз (40x) быстрее, чем на одном. Рост производительности не зависит от числа процессоров, т. е. для конфигурации из 24 процессоров он будет таким же, как для 48 процессоров. Рост производительности кластера (Cluster speedup) отличается только тем, что при его расчете берется число узлов, а не процессоров. Как и рост производительности SMP, рост производительности кластера остается постоянным для разного числа узлов.

Эффективность масштабирования (Scaling efficiency) характеризует способность приложений, особенно кластерных, масштабироваться на большое число узлов. Обычно считается, что эффективность масштабирования зависит от числа узлов, участвующих в измерении. Эффективность масштабирования SMP (SMP scaling efficiency) - это рост производительности, деленный на число процессоров, а эффективность кластера (Cluster efficiency) - это рост производительности кластера, деленный на число узлов в нем. Нужно понимать, в чем смысл этих параметров, чтобы не складывалась неправильная картина, поскольку эффективность масштабирования 90% на двух узлах - это не то же самое, что эффективность масштабирования 90% на четырех узлах.

На рис. 2 приведены три графика: идеальная линейная масштабируемость, масштабируемость 24-процессорного SMP-сервера в 95% и масштабируемость кластера из двух 4-процессорных серверов в 90%. Видно, что существуют определенные ограничения на масштабируемость баз данных в кластерах (при горизонтальном масштабировании). Соединяя вместе много маленьких серверов, не удается получить масштабируемость, необходимую для средних и крупных приложений. Причина этого - ограничения пропускной способности внутрикластерных межсоединений, дополнительная нагрузка на ПО баз данных, связанная с управлением кластером, и трудности написания приложений для кластерных сред с распределенной памятью.

Опубликованные результаты эталонных тестов показывают, например, что у Oracle9i RAC (Real Application Cluster) рост производительности составляет 1,8 и эффективность масштабирования равна 90%. Такая эффективность масштабируемости может показаться достаточно высокой, но на самом деле масштабируемость 90% для четырех узлов оказывается неэффективной, если сравнить ее с результатами больших SMP-серверов.

Производительность на уровне приложений

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

В большинстве случаев уровню сервера приложений требуется намного больше процессоров, чем уровню базы данных в расчете на отдельный прикладной сервис. Например, в случае SAP R/3 это соотношение составляет примерно 10 процессоров на каждый процессор базы данных, т. е. если SAP R/3 требуется 20 процессоров для уровня базы данных, то на уровне приложений должно быть примерно 200 процессоров. Вопрос заключается в том, что выгоднее развернуть - 100 двухпроцессорных серверов или десять 20-процессорных. Аналогичным образом в Oracle соотношение процессоров приложений к процессорам баз данных равно примерно 5 к 1.

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

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

В то же время расходы на управление и обслуживание инфраструктуры у горизонтальной архитектуры могут оказаться более высокими. При развертывании на горизонтальных системах используются многочисленные копии ОС и ПО серверов приложений. Затраты же на поддержание инфраструктуры обычно растут пропорционально числу копий ОС и приложений. Кроме того, для горизонтальной архитектуры резервное копирование и восстановление после аварий становится децентрализованным, и управлять сетевой инфраструктурой сложнее.

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

Влияние архитектуры на доступность

Доступность крайне важна для современных центров обработки данных - сервисы приложений должны быть доступны в режиме 24x7x365 (24 часа в сутки, 7 дней в неделю, 365 дней в году). В зависимости от потребностей конкретного центра обработки данных используются разные схемы обеспечения высокой доступности. Для выбора конкретного решения необходимо определить допустимое время простоев (запланированных и незапланированных). На рис. 3 показано, как процент доступности отражается на продолжительности простоев.

По мере роста требований к доступности растет и стоимость решения. Менеджеры центров обработки данных должны определить, какое сочетание стоимости, сложности и доступности наилучшим образом соответствует требованиям к уровню сервиса. Центры обработки данных, которым нужна доступность примерно 99,95%, могут развернуть одиночный SMP-сервер с такими функциями RAS, как полное резервирование аппаратуры и обслуживание в онлайновом режиме.

Однако для достижения доступности выше 99,95% потребуется кластер. ПО Sun Cluster с переключением при отказе HA (High Availability - высокой доступности) обеспечивает доступность 99,975%. Переключение при отказе HA использует основной сервер и находящийся в горячем резерве; при отказе основного сервера резервный берет на себя его нагрузку. Время перезапуска сервиса зависит от приложений и может занять несколько минут, особенно в случае приложений баз данных, которым для восстановления транзакций требуется откат с обработкой большого объема данных.

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

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

Для трехуровневой архитектуры хорошим примером горизонтальной высокой доступности служит развертывание Web-серверов. Можно развернуть много небольших серверов, на каждом из которых будет установлена отдельная копия ПО Web-сервера. Если один Web-сервер выйдет из строя, его транзакции перераспределяются между остальными работоспособными серверами. В случае серверов приложений они могут размещаться как на горизонтальных, так и на вертикальных серверах, и высокая доступность реализуется с помощью дублирования. Независимо от того, развертывается ли несколько крупных SMP-серверов или много небольших, дублирование остается основным способом обеспечения высокого RAS на уровне приложений.

Однако для уровня баз данных ситуация меняется. Базы данных сохраняют состояние и по своей природе требуют в большинстве случаев разделения данных и возможности доступа к ним со всех процессоров/узлов. Это означает, что для высокой доступности с помощью дублирования нужно использовать такое ПО кластеризации, как Sun Cluster или Oracle9i RAC (для очень высокой доступности).

Выводы

Как у вертикальной, так и у горизонтальной архитектуры есть своя ниша в сегодняшнем центре обработки данных. Хотя сегодня основное внимание сосредоточено на таких новых технологиях, как модульные серверы и параллельные базы данных, на рынке сохраняется высокий спрос на серверы среднего класса и класса high-end.

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

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

К концу 2012 года более 50% приложений работающих на х86 платформе виртуализированы. Вместе с тем виртуализировано только 20% бизнес критических приложений.

Это из-за того что ИТ отделы не доверяют платформам виртуализации? Считают ли они платформы виртуализации не достаточно стабильными для поддержки работы критически важных приложений?

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

Тогда если доверие или стабильность не являются проблемой в чём же причина того что ИТ отделы еще не виртуализировали оставшиеся приложения?

Scale out
Scale out или горизонтальное масштабирование - добавление новых ресурсов в инфраструктуру, например, серверов в кластер.

Так как цены продолжают падать, а производительность расти то дешёвые, commodity (широкого потребления) сервера являются идеальным решением для горизонтального масштабирования, и могут быть собраны в большие кластера для объединения вычислительных ресурсов.

Последние семь лет архитекторы инфраструктур на VMware молились на горизонтальное масштабирование. Кто-то может аргументировать за использование именного этого подхода, но он тоже имеет свои нюансы, и всё зависит от требований бизнеса. Плюс горизонтального масштабирования в том, что commodity сервера дёшевы, и в случае выхода сервера из строя это влияет на небольшое количество ВМ. Минус в бОльших затратах на лицензии на vSphere, большие требования к площади ЦОД, и обычно такие commodity сервера не обладают большими вычислительными ресурсами.

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

Обычно такие сервера довольно мощные - с поддержкой 4 процессоров и 512ГБ памяти. Кроме того встречаются системы с 8 процессорами и 1ТБ памяти, а некоторым повезло увидеть даже 16-ти процессорные сервера с 4ТБ памяти. И нет, это не мейнфреймы или что-то типа того, это сервера на основе классической х86 архитектуры.

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

  • Недостаточные возможности по масштабированию. Нагрузки с высокими требованиями к объёму вычислительных ресурсов являются проблемой из-за ограниченного объёма ресурсов доступных с дешёвыми commodity серверами.
  • Недостаточная надёжность. Commodity оборудование или аппаратное обеспечение использующее такие компоненты может быть менее надёжным. Проблему надёжности можно решить с помощью функций о которых я расскажу в следующих статьях.
  • Увеличение сложности управления и рост операционных расходов. Легче управлять 100 серверами, а не 1000, ну и, как следствие, 10 серверами управлять проще чем 100. Тоже самое касается и операционных расходов - 10 серверов гораздо дешевле поддерживать чем 100.
Вертикальное масштабирование отлично подходит для бизнес критических приложений с их огромными требованиями к ресурсам. Привет, Monster VM! Все эти прожорливые критичные базы данных, огромные ERP системы, системы аналитики больших данных, JAVA приложения и так далее и тому подобное получат прямую выгоду от вертикального масштабирования.

С выходом vSphere 5 количество ресурсов, доступных одной ВМ выросло в 4 раза.

А с выходом vSphere 5.1 монструозные ВМ могут быть еще монструознее.

Для того чтобы vSphere 5.1 могла запустить ВМ-монстра планировщику необходимо иметь и спланировать запуск потоков на 64 физических процессорах. Не так много серверов, которые могут поддерживать столько ядер, а серверов с поддержкой 16 сокетов и 160 ядер и того меньше.

Всего существует два типа вертикального масштабирования серверов: glueless и glued. На русский язык эти слова переводятся так: без интегрирующих технологий и с интегрирующими технологиями, соответственно.

Glueless архитектура
Данная архитектура была разработана в Intel, и представлена в Intel Xeon E7.

Для связи между устройствами ввода-вывода, сетевыми интерфейсами и процессорам используется специально разработанная шина QPI.

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

В 8-ми процессорном сервере каждый процессор напрямую подключается к трём соседним, и через другой процессор к другим четырём.

Преимущества такой архитектуры:

  • Нет необходимости в специальной разработке или специализации у производителя серверов
  • Любой производитель серверов может выпускать 8-ми процессорные сервера
  • Снижается стоимость как 4-ёх так и 8-ми процессорного сервера
Недостатки:
  • Общая стоимость владения растёт при горизонтальном масштабировании
  • Архитектура ограничена 8-ми процессорными серверами
  • Тяжело поддерживать целостность кэша при увеличении сокетов
  • Нелинейный рост производительности
  • Соотношение цены к производительности падает
  • Неоптимальная эффективность при использовании больших ВМ
  • Вплоть до 65% пропускной способности шины уходит на широковещательные сообщения болтливого протокола QPI
В чём же причина болтливости протокола QPI? Для того чтобы достичь целостности процессорного кэша каждая операция на чтение должна быть реплицирована на все процессоры. Это можно сравнить с широковещательным пакетом в IP сети. Каждый процессор должен проверить у себя затребованную строку памяти, и в случае использования последней версии данных предоставить её. В случае если актуальные данные находятся в другом кэше протокол QPI с минимальными задержками копирует данную строку памяти из удалённого кэша. Таким образом на репликацию каждой операции чтения тратиться пропускная способность шины и такты кэша, которые могли бы использоваться для передачи полезных данных.

Основные приложения, производительность которых страдает от недостатков протокола QPI это Java приложения, большие БД, чувствительные к задержкам приложения.

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

Glued архитектура
Для решения описанных выше проблем разработчики аппаратного обеспечения разработали glued архитектуру. Данная архитектура использует внешний контроллер нод для организации взаимосвязи островков QPI - кластеров процессоров.


Intel QPI предлагает специальное масштабируемое решение - eXternal Node-Controllers (или XNC), практическая реализация которого разрабатывается сторонними OEM компаниями. Внешний контроллер нод, используемый начиная с Intel Xeon E7-4800, со встроенным контроллером памяти, включает в себя также систему Cache Coherent Non-Uniform Memory Access (ccNUMA) задача которой отслеживать актуальность данных в каждой строке памяти процессорного кэша были актуальные данные.

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

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

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

  • Функциональное разделение
  • Классическое горизонтальное масштабирование
    • Концепции Shared Nothing и Stateless
    • Критика концепций Shared Nothing и Stateless
    • Связность кода и данных
  • Кеширование
    • Проблема инвалидации кеша
    • Проблема старта с непрогретым кешем

Начнем наш третий урок, посвященный бизнес-логике проекта. Это самая главная составляющая в обработке любого запроса. Для таких вычислений требуются бэкенды - тяжелые серверы с большими вычислительными мощностями. Если фронтенд не может отдать клиенту что-то самостоятельно (а как мы выяснили в прошлом номере, он без проблем можем сам отдать, к примеру, картинки), то он делает запрос бекенду. На бэкенде отрабатывается бизнес-логика, то есть формируются и обрабатываются данные, при этом данные хранятся в другом слое - сетевом хранилище, базе данных или файловой системе. Хранение данных - это тема следующего урока, а сегодня мы сосредоточимся на масштабировании бекенда.

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

Функциональное разделение

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

Несмотря на простоту, о подобном подходе многие забывают. Например, мы очень часто встречаем веб-проекты, где используется только одна база MySQL под совершенно различные типы данных. В одной базе лежат и статьи, и баннеры, и статистика, хотя по-хорошему это должны быть разные экземпляры MySQL. Если у вас есть функционально не связанные данные (как в этом примере), то их целесообразно разносить в разные экземпляры баз данных или даже физические серверы. Посмотрим на это с другой стороны. Если у вас есть в одном проекте и встроенная интегрированная баннерокрутилка, и сервис, который показывает посты пользователей, то разумное решение - сразу осознать, что эти данные никак не связаны между собой и поэтому должны жить в самом простом варианте в двух разных запущенных MySQL. Это относится и к вычисляющим бэкендам - они тоже могут быть разными. С совершенно разными настройками, с разными используемыми технологиями и написанные на разных языках программирования. Возвращаясь к примеру: для показа постов вы можете использовать в качестве бэкенда самый обычный PHP, а для баннерной системы вы можете запустить модуль к nginx’у. Соответственно, для постов вы можете выделить сервер с большим количеством памяти (ну PHP все-таки), при этом для баннерной системы память может быть не так важна, как процессорная емкость.

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

От авторов

Основным направлением деятельности нашей компании является решение проблем, связанных с высокой нагрузкой, консультирование, проектирование масштабируемых архитектур, проведение нагрузочных тестирований и оптимизация сайтов. В число наших клиентов входят инвесторы из России и со всего мира, а также проекты «ВКонтакте», «Эльдорадо», «Имхонет», Photosight.ru и другие. Во время консультаций мы часто сталкиваемся с тем, что многие не знают самых основ - что такое масштабирование и каким оно бывает, какие инструменты и для чего используются. Эта публикация продолжает серию статей «Учебник по высоким нагрузкам». В этих статьях мы постараемся последовательно рассказать обо всех инструментах, которые используются при построении архитектуры высоконагруженных систем.

Классическое горизонтальное масштабирование

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

Концепции Shared Nothing и Stateless

Рассмотрим две концепции - Shared Nothing и Stateless, которые могут обеспечить возможность горизонтального масштабирования.

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

Концепция Stateless означает, что процесс программы не хранит свое состояние. Пользователь пришел и попал на этот конкретный сервер, и нет никакой разницы, попал пользователь на этот сервер или на другой. После того как запрос будет обработан, этот сервер полностью забудет информацию об этом пользователе. Пользователь вовсе не обязан все свои следующие запросы отправлять на этот же сервер, не должен второй раз приходить на него же. Таким образом, мы можем динамически менять количество серверов и не заботиться о том, чтобы роутить пользователя на нужный сервак. Наверное, это одна из серьезных причин, почему веб так быстро развивается. В нем гораздо проще делать приложения, чем писать классические офлайновые программы. Концепция «ответ - запрос» и тот факт, что ваша программа живет 200 миллисекунд или максимум одну секунду (после чего она полностью уничтожается), привели к тому, что в таких распространенных языках программирования, как PHP, до сих пор нет сборщика мусора.

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

Критика концепций Shared Nothing и Stateless

Сегодня перед вебом возникают новые задачи, которые ставят новые проблемы. Когда мы говорим про Stateless, это означает, что каждые данные каждому пользователю мы заново тащим из хранилища, а это подчас бывает очень дорого. Возникает резонное желание положить какие-то данные в память, сделать не совсем Stateless. Это связано с тем, что сегодня веб становится все более и более интерактивным. Если вчера человек заходил в веб-почту и нажимал на кнопку «Reload», чтобы проверить новые сообщения, то сегодня этим уже занимается сервер. Он ему говорит: «О, чувак, пока ты сидел на этой страничке, тебе пришли новые сообщения».

Возникают новые задачи, которые приводят к тому, что подход с Shared Nothing и отсутствием состояния в памяти иногда не является обязательным. Мы уже сталкивались неоднократно с ситуациями наших клиентов, которым мы говорим: «От этого откажитесь, положите данные в память» и наоборот «Направляйте людей на один и тот же сервер». Например, когда возникает открытая чат-комната, людей имеет смысл роутить на один и тот же сервер, чтобы это все работало быстрее.

Расскажем про еще один случай, с которым сталкивались. Один наш знакомый разрабатывал на Ruby on Rails игрушку наподобие «Арены» (онлайн драки и бои). Вскоре после запуска он столкнулся с классической проблемой: если несколько человек находятся в рамках одного боя, каждый пользователь постоянно вытаскивает из БД данные, которые во время этого боя возникли. В итоге вся эта конструкция смогла дожить только до 30 тысяч зарегистрированных юзеров, а дальше она просто перестала работать.

Обратная ситуация сложилась у компании Vuga, которая занимается играми для Facebook. Правда, когда они столкнулись с похожей проблемой, у них были другие масштабы: несколько миллиардов SELECT’ов из PostgreSQL в день на одной системе. Они перешли полностью на подход Memory State: данные начали храниться и обслуживаться прямо в оперативной памяти. Итог: ребята практически отказались от базы данных, а пара сотен серверов оказались лишним. Их просто выключили: они стали не нужны.

В принципе, любое масштабирование (в том числе горизонтальное) достижимо на очень многих технологиях. Сейчас очень часто речь идет о том, чтобы при создании сервиса не пришлось платить слишком много за железо. Для этого важно знать, какая технология наиболее соответствует данному профилю нагрузки с минимальными затратами железа. При этом очень часто, когда начинают размышлять о масштабировании, то забывают про финансовый аспект того же горизонтального масштабирования. Некоторые думают, что горизонтальное масштабирование - это реально панацея. Разнесли данные, все разбросали на отдельные серверы - и все стало нормально. Однако эти люди забывают о накладных расходах (оверхедах) - как финансовых (покупка новых серверов), так эксплуатационных. Когда мы разносим все на компоненты, возникают накладные расходы на коммуникацию программных компонентов между собой. Грубо говоря, хопов становится больше. Вспомним уже знакомый тебе пример. Когда мы заходим на страничку Facebook, мощный JavaScript идет на сервер, который долго-долго думает и только через некоторое время начинает отдавать вам ваши данные. Все наблюдали подобную картину: хочется уже посмотреть и бежать дальше пить кофе, а оно все грузится, грузится и грузится. Надо бы хранить данные чуть-чуть «поближе», но у Facebook уже такой возможности нет.

Слоистость кода

Еще пара советов для упрощения горизонтального масштабирования. Первая рекомендация: программируйте так, чтобы ваш код состоял как бы из слоев и каждый слой отвечал за какой-то определенный процесс в цепочке обработки данных. Скажем, если у вас идет работа с базой данных, то она должна осуществляться в одном месте, а не быть разбросанной по всем скриптам. К примеру, мы строим страницу пользователя. Все начинается с того, что ядро запускает модуль бизнес-логики для построения страницы пользователя. Этот модуль запрашивает у нижележащего слоя хранения данных информацию об этом конкретном пользователе. Слою бизнес-логики ничего не известно о том, где лежат данные: закешированы ли они, зашардированы ли (шардинг - это разнесение данных на разные серверы хранения данных, о чем мы будем говорить в будущих уроках), или с ними сделали еще что-нибудь нехорошее. Модуль просто запрашивает информацию, вызывая соответствующую функцию. Функция чтения информации о пользователе расположена в слое хранения данных. В свою очередь, слой хранения данных по типу запроса определяет, в каком именно хранилище хранится пользователь. В кеше? В базе данных? В файловой системе? И далее вызывает соответствующую функцию нижележащего слоя.

Что дает такая слоистая схема? Она дает возможность переписывать, выкидывать или добавлять целые слои. Например, решили вы добавить кеширование для пользователей. Сделать это в слоистой схеме очень просто: надо допилить только одно место – слой хранения данных. Или вы добавляете шардирование, и теперь пользователи могут лежать в разных базах данных. В обычной схеме вам придется перелопатить весь сайт и везде вставить соответствующие проверки. В слоистой схеме нужно лишь исправить логику одного слоя, одного конкретного модуля.

Связность кода и данных

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

Что делать, если без JOIN’а не обойтись? Сделайте его сами: сделали два запроса, перемножили в PHP - в этом нет ничего страшного. Для примера рассмотрим классическую задачу построения френдленты. Вам нужно поднять всех друзей пользователя, для них запросить все последние записи, для всех записей собрать количество комментариев - вот где соблазн сделать это одним запросом (с некоторым количеством вложенных JOIN’ов) особенно велик. Всего один запрос - и вы получаете всю нужную вам информацию. Но что вы будете делать, когда пользователей и записей станет много и база данных перестанет справляться? По-хорошему надо бы расшардить пользователей (разнести равномерно на разные серверы баз данных). Понятно, что в этом случае выполнить операцию JOIN уже не получится: данные-то разделены по разным базам. Так что придется делать все вручную. Вывод очевиден: делайте это вручную с самого начала. Сначала запросите из базы данных всех друзей пользователя (первый запрос). Затем заберите последние записи этих пользователей (второй запрос или группа запросов). Затем в памяти произведите сортировку и выберите то, что вам нужно. Фактически вы выполняете операцию JOIN вручную. Да, возможно вы выполните ее не так эффективно, как это сделала бы база данных. Но зато вы никак не ограничены объемом этой базы данных в хранении информации. Вы можете разделять и разносить ваши данные на разные серверы или даже в разные СУБД! Все это совсем не так страшно, как может показаться. В правильно построенной слоистой системе большая часть этих запросов будет закеширована. Они простые и легко кешируются - в отличие от результатов выполнения операции JOIN. Еще один минус варианта с JOIN: при добавлении пользователем новой записи вам нужно сбросить кеши выборок всех его друзей! А при таком раскладе неизвестно, что на самом деле будет работать быстрее.

Кеширование

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

Второй важный момент. Кеш - это скорее способ замазать проблему производительности, а не решить ее. Но, безусловно, бывают ситуации, когда решить проблему очень дорого. Поэтому вы говорите: «Хорошо, эту трещину в стене я замажу штукатуркой, и будем думать, что ее здесь нет». Иногда это работает - более того, это работает очень даже часто. Особенно когда вы попадаете в кеш и там уже лежат данные, которые вы хотели показать. Классический пример - счетчик количества друзей. Это счетчик в базе данных, и вместо того, чтобы перебирать всю базу данных в поисках ваших друзей, гораздо проще эти данные закешировать (и не пересчитывать каждый раз).

Для кеша есть критерий эффективности использования, то есть показатель того, что он работает, - он называется Hit Ratio. Это отношение количества запросов, для которых ответ нашелся в кеше, к общему числу запросов. Если он низкий (50–60%), значит, у вас есть лишние накладные расходы на поход к кешу. Это означает, что практически на каждой второй странице пользователь, вместо того чтобы получить данные из базы, еще и ходит к кешу: выясняет, что данных для него там нет, после чего идет напрямую к базе. А это лишние две, пять, десять, сорок миллисекунд.

Как обеспечивать хорошее Hit Ratio? В тех местах, где у вас база данных тормозит, и в тех местах, где данные можно перевычислять достаточно долго, там вы втыкаете Memcache, Redis или аналогичный инструмент, который будет выполнять функцию быстрого кеша, - и это начинает вас спасать. По крайней мере, временно.

Олег Бунин

Известный специалист по Highload-проектам. Его компания «Лаборатория Олега Бунина» специализируется на консалтинге, разработке и тестировании высоконагруженных веб-проектов. Сейчас является организатором конференции HighLoad++ (www.highload.ru). Это конференция, посвященная высоким нагрузкам, которая ежегодно собирает лучших в мире специалистов по разработке крупных проектов. Благодаря этой конференции знаком со всеми ведущими специалистами мира высоконагруженных систем.

Константин Осипов

Специалист по базам данных, который долгое время работал в MySQL, где отвечал как раз за высоконагруженный сектор. Быстрота MySQL - в большой степени заслуга именно Кости Осипова. В свое время он занимался масштабируемостью MySQL 5.5. Сейчас отвечает в Mail.Ru за кластерную NoSQL базу данных Tarantool, которая обслуживает 500–600 тысяч запросов в секунду. Использовать этот Open Source проект может любой желающий.

Максим Лапшин

Решения для организации видеотрансляции, которые существуют в мире на данный момент, можно пересчитать по пальцам. Макс разработал одно из них - Erlyvideo (erlyvideo.org). Это серверное приложение, которое занимается потоковым видео. При создании подобных инструментов возникает целая куча сложнейших проблем со скоростью. У Максима также есть некоторый опыт, связанный с масштабированием средних сайтов (не таких крупных, как Mail.Ru). Под средними мы подразумеваем такие сайты, количество обращений к которым достигает около 60 миллионов в сутки.

Константин Машуков

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

Проблема инвалидации кеша

Но с использованием кеша вы бонусом получаете проблему инвалидации кеша. В чем суть? Вы положили данные в кеш и берете их из кеша, однако к этому моменту оригинальные данные уже поменялись. Например, Машенька поменяла подпись под своей картинкой, а вы зачем-то положили одну строчку в кеш вместо того, чтобы тянуть каждый раз из базы данных. В результате вы показываете старые данные - это и есть проблема инвалидации кеша. В общем случае она не имеет решения, потому что эта проблема связана с использованием данных вашего бизнес-приложения. Основной вопрос: когда обновлять кеш? Ответить на него подчас непросто. Например, пользователь публикует в социальной сети новый пост - допустим, в этот момент мы пытаемся избавиться от всех инвалидных данных. Получается, нужно сбросить и обновить все кеши, которые имеют отношение к этому посту. В худшем случае, если человек делает пост, вы сбрасываете кеш с его ленты постов, сбрасываете все кеши с ленты постов его друзей, сбрасываете все кеши с ленты людей, у которых в друзьях есть те, кто в этом сообществе, и так далее. В итоге вы сбрасываете половину кешей в системе. Когда Цукерберг публикует пост для своих одиннадцати с половиной миллионов подписчиков, мы что - должны сбросить одиннадцать с половиной миллионов кешей френдлент у всех этих subscriber’ов? Как быть с такой ситуацией? Нет, мы пойдем другим путем и будем обновлять кеш при запросе на френдленту, где есть этот новый пост. Система обнаруживает, что кеша нет, идет и вычисляет заново. Подход простой и надежный, как скала. Однако есть и минусы: если сбросился кеш у популярной страницы, вы рискуете получить так называемые race-condition (состояние гонок), то есть ситуацию, когда этот самый кеш будет одновременно вычисляться несколькими процессами (несколько пользователей решили обратиться к новым данным). В итоге ваша система занимается довольно пустой деятельностью - одновременным вычислением n-го количества одинаковых данных.

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

Проблема старта с непрогретым кешем

Еще одна проблема - старт с непрогретым (то есть незаполненным) кешем. Такая ситуация наглядно иллюстрирует утверждение о том, что кеш не может решить проблему медленной базы данных. Предположим, что вам нужно показать пользователям 20 самых хороших постов за какой-либо период. Эта информация была у вас в кеше, но к моменту запуска системы кеш был очищен. Соответственно, все пользователи обращаются к базе данных, которой для построения индекса нужно, скажем, 500 миллисекунд. В итоге все начинает медленно работать, и вы сами себе сделали DoS (Denial-of-service). Сайт не работает. Отсюда вывод: не занимайтесь кешированием, пока у вас не решены другие проблемы. Сделайте, чтобы база быстро работала, и вам не нужно будет вообще возиться с кешированием. Тем не менее даже у проблемы старта с незаполненным кешем есть решения:

  1. Использовать кеш-хранилище с записью на диск (теряем в скорости);
  2. Вручную заполнять кеш перед стартом (пользователи ждут и негодуют);
  3. Пускать пользователей на сайт партиями (пользователи все так же ждут и негодуют).

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