← Назад к вопросам
В чем разница между вертикальным и горизонтальным масштабированиями?
2.0 Middle🔥 91 комментариев
#REST API и микросервисы
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между вертикальным и горизонтальным масштабированием
Масштабирование — это способность системы обрабатывать растущую нагрузку. Существуют два основных подхода, каждый со своими преимуществами и недостатками.
Вертикальное масштабирование (Vertical Scaling)
Определение: Увеличение мощности отдельного сервера — добавление больше CPU, RAM, дискового пространства.
До: После вертикального:
┌──────────────┐ ┌──────────────────────┐
│ Сервер │ │ Сервер (усиленный) │
│ 4 CPU │ → │ 16 CPU │
│ 8 GB RAM │ │ 64 GB RAM │
│ 100 GB SSD │ │ 1 TB SSD │
└──────────────┘ └──────────────────────┘
Примеры:
// Вертикальное масштабирование
// До: t2.small (1 vCPU, 2 GB RAM) на AWS
// После: t3.2xlarge (8 vCPU, 32 GB RAM) на AWS
Преимущества:
- Просто реализовать — просто обновите сервер
- Нет изменений в коде приложения
- Нет сложности с распределённостью
- Проще с состоянием (state) — всё на одном сервере
- Единая БД, нет проблем консистентности
// Приложение остаётся как есть:
public class SimpleApp {
public static void main(String[] args) {
Server server = new Server(8080);
server.start(); // Обработает больше запросов благодаря мощнее CPU/RAM
}
}
Недостатки:
- Физический лимит — нет сервера с бесконечной мощностью
- Дорого — очень мощные серверы стоят экспоненциально дороже
- Downtime — нужно остановить сервер для обновления
- Single point of failure — один сервер = один отказ
- Нет распределения нагрузки — всё идёт на один узел
Вертикальное масштабирование имеет потолок:
┌─────────────┐
│ Мощность │ ←← Здесь лимит
│ сервера │ (самый мощный железо)
└─────────────┘
▲
│ Стоимость растёт экспоненциально!
│ (2x мощности ≠ 2x стоимость)
Горизонтальное масштабирование (Horizontal Scaling)
Определение: Увеличение количества серверов в системе, распределяя нагрузку между ними.
До: После горизонтального:
┌──────────────┐
│ Сервер │ ┌──────────────┐
│ 4 CPU │ │ Сервер 1 │
│ 8 GB RAM │ → │ 4 CPU, 8GB │
└──────────────┘ └──────────────┘
┌──────────────┐
│ Сервер 2 │
│ 4 CPU, 8GB │
└──────────────┘
┌──────────────┐
│ Сервер 3 │
│ 4 CPU, 8GB │
└──────────────┘
┌────────────────────┐
│ Load Balancer │
└────────────────────┘
Архитектура с горизонтальным масштабированием:
// Load Balancer (Nginx, HAProxy, облачные сервисы)
public class LoadBalancer {
private List<Server> servers = Arrays.asList(
new Server("server1:8080"),
new Server("server2:8080"),
new Server("server3:8080")
);
public void handleRequest(Request req) {
// Round-robin, least connections, IP hash и т.д.
Server selected = selectServer(); // Выбираем сервер
selected.handle(req); // Отправляем запрос
}
}
Преимущества:
- Нет физического лимита — можно добавлять серверы бесконечно
- Дешевле — много дешёвых серверов дешевле одного супер-мощного
- Без downtime — добавляем новый сервер, не трогая старые
- Отказоустойчивость — если один сервер упадёт, другие работают
- Гибкость — быстро реагируем на спайки нагрузки (автоскейлинг)
Горизонтальное масштабирование масштабируется линейно:
┌──────────────────────────────┐
│ Мощность системы │
│ ▲ │ ← Растёт линейно
│ │ ╱╱ │ (N серверов = N × мощность)
│ │ ╱╱ │
│ │╱╱ │
└──────────────────────────────┘
Количество серверов →
Недостатки:
- Сложность — нужна согласованность данных между серверами
- Stateless приложение — сложнее работать с состоянием
- Сеть — больше сетевых вызовов, latency растёт
- Синхронизация БД — сложная проблема с репликацией/шардингом
- Operationalная сложность — нужен Load Balancer, мониторинг, автоскейлинг
Практический пример: Java приложение
Вертикальное масштабирование:
// Просто запускаем на более мощном сервере
public class Application {
public static void main(String[] args) {
// Было: На сервере t2.small (1 vCPU, 2 GB)
// Теперь: На сервере t3.2xlarge (8 vCPU, 32 GB)
// Код не меняется!
ExecutorService executor = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors() // Автоматически 8 потоков
);
Server server = new Server(8080);
server.start();
}
}
Горизонтальное масштабирование:
// Нужны изменения в коде
public class DistributedApplication {
public static void main(String[] args) {
// Три инстанса приложения, слой load balancer
// 1. Stateless контроллеры (обработка запросов)
@RestController
public class UserController {
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
// Каждый сервер может обработать любой запрос
return userService.findById(id);
}
}
// 2. Сессии хранятся в Redis, не в памяти сервера
// (иначе клиент может попасть на другой сервер и потеряет сессию)
@Bean
public LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory();
}
// 3. Кеши должны быть распределёнными
@Bean
public CacheManager cacheManager(LettuceConnectionFactory factory) {
return RedisCacheManager.create(factory);
}
}
}
Сравнительная таблица
| Параметр | Вертикальное | Горизонтальное |
|---|---|---|
| Реализация | Просто | Сложно |
| Стоимость | Высокая при росте | Линейная |
| Downtime | Требуется | Нет |
| Отказоустойчивость | Низкая | Высокая |
| Лимиты | Есть | Нет |
| Изменения в коде | Минимум | Много |
| Latency | Низкий | Может быть выше |
| Консистентность данных | Простая | Сложная |
| Автоскейлинг | Нет | Да |
Рекомендации
Используйте вертикальное, если:
- Нагрузка предсказуема и не очень высока
- Приложение имеет состояние (stateful)
- Команда небольшая, нет опыта с распределёнными системами
- Простота важнее масштабируемости
Используйте горизонтальное, если:
- Нагрузка высокая и непредсказуема
- Нужна отказоустойчивость
- Приложение может быть stateless
- Важна надёжность и отказоустойчивость
На практике: Современные системы обычно комбинируют оба подхода:
- Горизонтальное масштабирование приложений
- Вертикальное масштабирование БД (с кластерами для отказоустойчивости)
- Кеширование (Redis) для снижения нагрузки на БД