Масштабирование отвечает на вопрос: что делать, когда один сервер перестал справляться.
Вертикальное и горизонтальное
- Вертикальное (scale up): больше CPU, памяти, быстрее диск. Просто, код не меняется. Предел: самый большой сервер и его цена, плюс единая точка отказа.
- Горизонтальное (scale out): больше одинаковых узлов. Почти без предела, даёт отказоустойчивость, но требует, чтобы сервис был stateless или состояние было распределено.
Для БД начинают с вертикального: современный сервер с 64 ядрами и 512 ГБ памяти держит очень много. Горизонтально проще всего масштабировать stateless-сервисы приложения.
Stateless-сервисы
Сервис stateless, если любой его экземпляр может обработать любой запрос. Сессии, загруженные файлы, кеш выносятся во внешние хранилища: Redis, S3, БД. Тогда экземпляры можно добавлять и убирать автоматически (автоскейлинг в Kubernetes по CPU или RPS).
Балансировка нагрузки
Балансировщик распределяет запросы между узлами и убирает из ротации больные (health checks).
- L4 (транспортный уровень): смотрит на IP и порт, очень быстрый, не видит HTTP.
- L7 (прикладной уровень): видит URL, заголовки, cookie; умеет маршрутизировать по пути, терминировать TLS. Примеры: nginx, Envoy, HAProxy в режиме http.
Алгоритмы: round robin, weighted round robin, least connections, хеширование по ключу (IP или id пользователя) для «прилипания» к узлу.
Репликация БД
Лидер принимает запись, реплики получают изменения и обслуживают чтение.
- Асинхронная: запись быстрая, но реплика отстаёт (replication lag). Пользователь может не увидеть только что сохранённое.
- Синхронная: лидер ждёт подтверждения реплики, данные не теряются при падении лидера, но запись медленнее.
Типичная проблема: read-your-writes. Решение: читать свои свежие данные с лидера в течение нескольких секунд после записи, или по версии.
Шардирование
Когда данные или запись не помещаются в один узел, их делят на шарды по ключу.
- По диапазону: удобно для запросов по интервалу, но риск горячего шарда (все новые записи в последний).
- По хешу: равномерно, но запросы по диапазону идут во все шарды.
- Консистентное хеширование: при добавлении узла переезжает только около 1/N ключей, а не почти все, как при
hash % N. Виртуальные узлы сглаживают неравномерность.
Выбор ключа шардирования главный: запросы должны в основном попадать в один шард. Для мессенджера логично шардировать по chat_id, для заказов по user_id.
Цена шардирования: JOIN и транзакции между шардами становятся сложными, решардинг болезненный.
CDN
Статика и медиа раздаются с серверов рядом с пользователем. Снимает трафик с origin и сокращает задержку с сотен до десятков миллисекунд.
Частые ошибки
- Шардировать сразу, когда хватит одного сервера с репликами.
- Хранить сессии в памяти процесса и удивляться разлогинам за балансировщиком.
- Использовать
hash(key) % Nи при добавлении узла перетасовать почти все данные. - Забыть про отставание реплик.
Что спросят на собесе
- Чем вертикальное масштабирование отличается от горизонтального, плюсы и минусы.
- Что такое stateless и зачем он нужен.
- L4 и L7 балансировщики: разница.
- Как выбрать ключ шардирования и что такое горячий шард.
- Зачем консистентное хеширование.