Реальный пример проекта
Пример высоконагруженной системы
Как мы планировали архитектуру и работали с рисками, чтобы получить желаемые показатели производительности на заявленных объемах данных и количестве запросов.
Обработка 100 000 запросов в секунду
Ответ в течение 100 мс
Поиск по критериям и выполнение нескольких логических операций для каждого запроса
Основные проблемы и риски
Проект был связан с интернет рекламой, где любая ошибка могла привести к потере десятков тысяч долларов за считанные минуты.
Главный риск заключался в том, что выбранный технологический стек не сможет справиться с большим количеством запросов и обеспечить требуемое время отклика.
Процесс разработки высоконагруженной системы
01
Выбор технологического стека:
Выбранный технологический стек должен был соответствовать следующим требованиям:
Неблокирующий асинхронный ввод-вывод: Синхронный ввод-вывод сделал бы невозможным соблюдение задержки не более 100 мс при такой нагрузке.
Индекс в оперативной памяти для поиска: Это позволяет сократить время на сетевые взаимодействия.
Отсутствие внутреннего состояния для процесса, обрабатывающего входящие запросы: Это обеспечивает возможность долгосрочного горизонтального масштабирования.
02
Создание прототипа
Мы разработали прототип, включающий выбранный технологический стек.
03
Создание тестовой среды
Мы создали тестовую среду для высоконагруженной системы на основе wrk2 с использованием Lua-скриптов для нагрузки запросами и измерения времени отклика.
Ключевым моментом было то, что мы не загружали процесс случайными данными. Вместо этого мы использовали запросы, которые действительно находили данные в индексе, имитируя реальную работу.
Для этого мы разработали генератор тестовых данных, чтобы заполнить индекс и создать запросы, соответствующие тестовым данным, с примерно тем же процентом успешных поисков, который ожидался в реальных условиях.
04
Проведение тестов и оптимизация
Когда все компоненты были готовы, мы начали проводить тесты. Анализ результатов позволил нам внести несколько важных улучшений, достигнув скорости обработки около 5 000 запросов в секунду на один процесс. Кроме того, мы обеспечили возможность горизонтального масштабирования процессов.
05
Требования к сборке и развертыванию
После устранения рисков мы перешли к развертыванию. Для таких систем предпочтительно начинать с облачного развертывания. В данном случае мы использовали облако Яндекс с Kubernetes и декларативным описанием инфраструктуры в Terraform.
Процесс развертывания выглядел следующим образом: сначала мы собирали Docker-образы всех компонентов на нашем GitLab CI, загружали их в приватный реестр Docker и создавали конфигурацию Terraform, которая указывала облаку, где и что развертывать, включая количество экземпляров.
Этот подход упростил развертывание новых версий: мы создавали новые образы, обновляли их версии в конфигурации Terraform и применяли изменения.
06
Дополнительные требования к системе
В высоконагруженных системах важны мониторинг и система защиты.
Мониторинг включает сбор метрик со всех компонентов (например, загрузка ресурсов, время выполнения запросов, количество ошибок) и их визуализацию в удобном формате для оператора системы.
Мы использовали Prometheus для сбора метрик и Grafana для их визуализации. Также были настроены оповещения, отправляющие сообщения через мессенджеры при приближении метрик к критическим значениям, что позволяло оперативно реагировать.
Система защиты предотвращает ущерб при сбоях. Например, если компонент выходит из строя или ухудшает производительность (допустим, в Clickhouse заканчивается место на диске), другие компоненты обнаруживают это и прекращают выполнять потенциально опасные операции, связанные с финансами, чтобы избежать лишних затрат. В системе было около десяти защитных механизмов.
07
Хранилища данных
Система включала три разных типа хранилищ данных, так как для такой нагрузки и требований к времени отклика важно использовать специализированные хранилища для каждой задачи.
Для быстрого сохранения миллионов новых записей оптимальным выбором был Clickhouse. Он оптимизирован для быстрой вставки данных и подходит для промежуточного хранения больших объемов данных или аналитики, но медленнее при изменении или удалении данных.
Для быстрого получения значений по ключу (быстрее 10 мс) из централизованного хранилища мы использовали Aerospike, так как каждый его экземпляр может обрабатывать до 100 000 операций в секунду. В нашей системе было четыре экземпляра.
Для хранения различных конфигураций мы использовали стандартную реляционную СУБД PostgreSQL.
08
Создание системы, способной эффективно справляться с высокими нагрузками
Убедившись, что все работает, мы перенесли систему из облака на собственную инфраструктуру, чтобы значительно сократить расходы. Благодаря использованию Terraform и Kubernetes этот переход был достаточно простым.
Чтобы узнать больше о нашем опыте, посетите страницу разработки высоконагруженных систем
Узнать большеТрансформируйте свой бизнес уже сегодня –
Получите бесплатную консультацию
Свяжитесь с нами, и первая консультация будет бесплатной.