Перейти к содержимому

Основы масштабирования

Масштабирование — это способность системы увеличивать производительность при росте нагрузки. Два основных типа: вертикальное (Scaling Up) — увеличение мощности одного сервера (просто, есть потолок, дорого на больших объёмах) и горизонтальное (Scaling Out) — добавление новых серверов (сложно, практически безлимитно, дешевле на больших объёмах). Stateless компоненты (веб-серверы) масштабируются горизонтально легко через балансировщик, stateful (базы данных) — сложно через репликацию (масштабирование чтения) и шардирование (масштабирование записи). Ключевые законы: Амдала (ускорение ограничено последовательной частью) и Гюнтера (накладные расходы на синхронизацию). Типичные этапы роста: один сервер → отдельная БД → кэш → репликация БД → горизонтальное масштабирование приложения → шардирование БД → микросервисы. Главные ошибки: преждевременное шардирование, масштабирование без устранения узких мест (обычно базы данных) и игнорирование экономики (для малых нагрузок вертикальное масштабирование дешевле).

Введение: Когда один сервер перестаёт справляться

Представьте, что у вас есть небольшой магазин. За день заходит 50 человек — вы справляетесь. Через месяц — 500 человек. Вы нанимаете ещё одного продавца. Через год — 5000 человек в день. Ваш маленький магазин не вмещает всех. Что делать? Можно переехать в огромный торговый центр (вертикальное масштабирование). А можно открыть несколько магазинов в разных районах города (горизонтальное масштабирование).

С базами данных и серверами та же история. Сначала вы ставите всё на один сервер. Данных немного, запросов мало. Потом бизнес растёт. Данных становится всё больше. Запросов — всё больше. Один сервер перестаёт справляться: медленные ответы, долгие бэкапы, высокий CPU.

Масштабирование — это способность системы увеличивать свою производительность и ёмкость при росте нагрузки. Хорошо масштабируемая система при увеличении ресурсов (добавлении серверов, увеличении мощности) показывает пропорциональный рост производительности.

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

Два типа масштабирования

ТипЧто делаемАналогия
ВертикальноеУвеличиваем мощность одного сервераПереезжаем в больший офис
ГоризонтальноеДобавляем новые серверыОткрываем филиалы

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

Что это

Вы берёте существующий сервер и делаете его мощнее: больше CPU, больше RAM, быстрее диски. Или переезжаете на более крупный сервер в облаке.

Как это выглядит

Было:
  - 4 CPU, 16 GB RAM, SSD 500 GB

Стало:
  - 16 CPU, 64 GB RAM, SSD 2 TB

Преимущества

ПреимуществоОбъяснение
ПростотаНе нужно менять архитектуру приложения
СовместимостьВсе функции базы данных работают как раньше
ТранзакцииACID, внешние ключи, JOIN — всё сохраняется
УправлениеОдин сервер проще администрировать

Недостатки

НедостатокОбъяснение
Физический пределНельзя бесконечно увеличивать мощность
СтоимостьСамые мощные серверы очень дороги
Отсутствие отказоустойчивостиСервер упал — всё упало
Простой при апгрейдеЧтобы увеличить память, часто нужна остановка

Когда использовать

Подходит:
  - Начальный этап (пока нагрузки мало)
  - Данные помещаются на один сервер
  - Бюджет позволяет купить мощный сервер
  - Нет времени/ресурсов на сложную архитектуру

Не подходит:
  - Данные > 10 ТБ (дорого)
  - Запросов > 10 000 в секунду
  - Нужна отказоустойчивость

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

Что это

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

Как это выглядит

Было:
  - 1 сервер (4 CPU, 16 GB RAM)

Стало:
  - 5 серверов (каждый 4 CPU, 16 GB RAM)
  - Итого: 20 CPU, 80 GB RAM

Преимущества

ПреимуществоОбъяснение
Теоретически безлимитноМожно добавлять серверы бесконечно
ДешевлеМного маленьких серверов дешевле одного огромного
ОтказоустойчивостьЕсли один сервер упал, другие работают
ГибкостьМожно добавлять серверы по мере роста

Недостатки

НедостатокОбъяснение
СложностьПриложение должно знать о нескольких серверах
Ограниченные возможностиНе все базы данных хорошо шардируются
ТранзакцииРаспределённые транзакции сложны
JOINJOIN между разными серверами медленные или невозможны

Когда использовать

Подходит:
  - Данные > 1 ТБ
  - Запросов > 10 000 в секунду
  - Нужна отказоустойчивость
  - Бюджет ограничен (много маленьких серверов дешевле)

Не подходит:
  - Маленькие проекты (избыточно)
  - Требуются сложные транзакции
  - Команда не имеет опыта распределённых систем

Горизонтальное vs Вертикальное: Сравнение

    graph TD
    subgraph "Вертикальное масштабирование"
        V1[Один большой сервер] --> V2[Ещё больше]
    end
    
    subgraph "Горизонтальное масштабирование"
        H1[Сервер 1] --> H2[Сервер 2]
        H1 --> H3[Сервер 3]
        H1 --> H4[Сервер 4]
    end
  
АспектВертикальноеГоризонтальное
ПределЕсть (максимальный сервер)Практически нет
СложностьНизкаяВысокая
Стоимость (на малых объемах)ДешевлеДороже
Стоимость (на больших объемах)ДорожеДешевле
ОтказоустойчивостьНет (одна точка отказа)Да
Изменение архитектурыНе требуетсяТребуется

Что масштабировать: Stateless vs Stateful

Stateless приложения (без состояния)

Приложение не хранит данные между запросами. Каждый запрос может быть обработан любым экземпляром.

Примеры: веб-сервер (nginx), API Gateway, функции (AWS Lambda).

Масштабирование: Простое горизонтальное. Добавляем копии за балансировщиком. Нет проблем с синхронизацией.

    graph LR
    LB[Балансировщик] --> App1[Приложение 1]
    LB --> App2[Приложение 2]
    LB --> App3[Приложение 3]
  

Stateful приложения (с состоянием)

Приложение хранит данные между запросами. Сессии, базы данных, очереди.

Примеры: PostgreSQL, Redis, Kafka.

Масштабирование: Сложное. Нужно синхронизировать состояние между экземплярами (репликация, шардирование, консенсус).

Показатели масштабируемости

Масштабируемость по нагрузке (Scalability)

  • Линейная. Удвоили серверы → удвоили производительность. Идеал.
  • Суб-линейная. Удвоили серверы → производительность выросла на 80%. Хорошо.
  • Сверх-линейная. Удвоили серверы → производительность выросла на 150%. Редко, бывает из-за кэшей.

Законы масштабирования

Закон Амдала. Ускорение системы ограничено самой медленной последовательной частью. Если 50% кода не может быть распараллелено, то даже бесконечное количество серверов даст ускорение не более чем в 2 раза.

Закон Гюнтера (USL - Universal Scalability Law). Учитывает не только последовательную часть, но и накладные расходы на синхронизацию. При росте числа процессоров сначала ускорение растёт, потом достигает пика, а потом может даже падать из-за contention (конкуренции за общие ресурсы).

    graph LR
    X[Число серверов] --> Y[Производительность]
    X2[1] --> Y2[100]
    X3[2] --> Y3[180]
    X4[4] --> Y4[300]
    X5[8] --> Y5[320]
    X6[16] --> Y6[310]
  

Узкие места (Bottlenecks) в масштабировании

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

Общие узкие места:

  • База данных. Много серверов приложений бьют в одну БД. БД не масштабируется.
  • Сеть. Пропускная способности сети может не хватить.
  • Дисковая подсистема. IOPS диска ограничен.
  • Архитектура. Последовательные части (по закону Амдала).
    graph TD
    App1[Приложение 1] --> DB[(Одна БД)]
    App2[Приложение 2] --> DB
    App3[Приложение 3] --> DB
    App100[100 приложений] --> DB
    
    DB -->|узкое место| Problem
  

Стратегии масштабирования

Масштабирование чтения (Read Scaling)

Когда запросов на чтение больше, чем на запись.

Решение: Репликация (Replication). Один мастер (пишем), много реплик (читаем).

    graph LR
    Master[Мастер<br/>запись] --> Replica1[Реплика 1<br/>чтение]
    Master --> Replica2[Реплика 2<br/>чтение]
    Master --> Replica3[Реплика 3<br/>чтение]
  

Масштабирование записи (Write Scaling)

Когда запросов на запись много, репликация не помогает (пишем всё равно в один мастер).

Решение: Шардирование (Sharding). Данные разбиваются на части (шарды), каждый шард на отдельном сервере.

    graph LR
    Shard1[Шард 1<br/>пользователи 1-1000]
    Shard2[Шард 2<br/>пользователи 1001-2000]
    Shard3[Шард 3<br/>пользователи 2001-3000]
  

Масштабирование и база данных

ПодходПростотаЭффективность
ВертикальноеВысокаяСредняя
РепликацияСредняяВысокая (для чтения)
ШардированиеНизкаяВысокая (для записи)

План масштабирования: этапы роста

Этап 1: Один сервер. Всё на одном сервере: приложение + БД. Просто, дёшево.

Этап 2: Отдельный сервер БД. Приложение на одном сервере, БД на другом. Уже лучше.

Этап 3: Кэш. Добавляем Redis для кэширования часто запрашиваемых данных.

Этап 4: Репликация БД. Мастер (запись) + реплики (чтение). Масштабируем чтение.

Этап 5: Горизонтальное масштабирование приложения (stateless). Несколько копий приложения за балансировщиком.

Этап 6: Шардирование БД. Данные разбиваются на шарды. Сложно.

Этап 7: Микросервисы. Разделение приложения на сервисы, каждый со своей БД.

    graph LR
    S1[1 сервер] --> S2[App + БД отдельно]
    S2 --> S3[+ кэш]
    S3 --> S4[+ реплики БД]
    S4 --> S5[+ горизонтальное App]
    S5 --> S6[+ шардирование БД]
    S6 --> S7[+ микросервисы]
  

Распространённые ошибки

Ошибка 1: Позднее масштабирование

Ждут, пока сервер упадёт, и только тогда начинают думать о масштабировании.

Решение: Мониторить CPU, RAM, IOPS, размер данных. Планировать масштабирование заранее.

Ошибка 2: Шардирование преждевременно

Шардирование на 100 серверов, когда данных на 10 GB. Сложность не оправдана.

Решение: Начинать с вертикального. Переходить на горизонтальное только когда вертикальное упёрлось в потолок.

Ошибка 3: Масштабирование без устранения узких мест

Добавляют серверы приложений, но база данных остаётся одна. Толку нет.

Решение: Найти узкое место (профилирование). Масштабировать узкое место.

Ошибка 4: Игнорирование стоимости

Горизонтальное масштабирование на маленьких объемах дороже вертикального.

Решение: Считать стоимость. Для 1000 пользователей вертикальное дешевле.

Стоимость масштабирования

Вертикальное

Сервер 4 CPU, 16 GB: $100/мес
Сервер 16 CPU, 64 GB: $400/мес
Сервер 64 CPU, 256 GB: $2000/мес

Цена растёт нелинейно.

Горизонтальное

5 серверов по 4 CPU, 16 GB: 5 × $100 = $500/мес
10 серверов по 4 CPU, 16 GB: 10 × $100 = $1000/мес

Цена растёт линейно.

Вывод: Для больших объёмов горизонтальное масштабирование дешевле. Для маленьких — вертикальное.

Резюме

Масштабирование — это способность системы увеличивать производительность при росте нагрузки.

Два типа:

  • Вертикальное — увеличиваем мощность одного сервера. Просто, но есть потолок, дорого на больших объёмах.
  • Горизонтальное — добавляем новые серверы. Сложно, но безлимитно, дешевле на больших объёмах.

Stateless vs Stateful:

  • Stateless (веб-серверы) масштабируются горизонтально легко.
  • Stateful (БД) масштабируются сложно (репликация, шардирование).

Законы масштабирования:

  • Закон Амдала: ускорение ограничено последовательной частью.
  • USL: синхронизация создаёт накладные расходы.

Узкие места: БД, сеть, диск, архитектура.

Этапы роста: 1 сервер → отдельная БД → кэш → репликация БД → горизонтальное приложение → шардирование БД → микросервисы.

Распространённые ошибки: Позднее масштабирование, преждевременное шардирование, игнорирование узких мест, игнорирование стоимости.

Масштабирование — это не только про технику, но и про экономику. Для маленьких проектов вертикальное масштабирование дешевле и проще. Для больших — горизонтальное неизбежно, но требует инвестиций в архитектуру. Главное — масштабироваться осознанно, когда это действительно нужно, а не “на всякий случай”.

Проверка знаний

Вопрос 1 из 4
Что означает масштабируемость системы?
Какие два базовых типа масштабирования выделяются в теме?
Что обычно называют bottleneck в контексте масштабирования?
Почему плохая масштабируемость опасна для бизнеса?

Вопросы, где были ошибки