Какие решения предложить при росте нагрузки на систему
Что проверяют
Умеете ли вы сначала найти узкое место, а потом выбирать решение, и понимаете ли разницу между онлайн-сервисом с моделью и пакетным конвейером данных. Следом обычно спрашивают, что вы сделаете первым делом и сколько это будет стоить.
Как отвечать
Начните с диагностики: какой этап не справляется (приём данных, обработка, хранилище, инференс) и во что он упирается: процессор, память, диск, сеть или GPU. Смотрите на p95 и p99 задержки, отставание консьюмеров, длительность задач в конвейере. Потом решения по слоям:
- инференс: реплики за балансировщиком и автоскейлинг в Kubernetes по RPS или длине очереди (HPA, KEDA). Динамический батчинг в Triton или vLLM поднимает пропускную способность GPU. Квантизация, ONNX Runtime и дистилляция удешевляют сам вызов, а кеш предсказаний и эмбеддингов снимает повторные запросы;
- пакетная обработка: инкрементальная загрузка вместо полного пересчёта, партиционирование по дате, колоночные форматы и табличные форматы вроде Iceberg или Delta. В Spark проверьте перекос данных: AQE включён по умолчанию с версии 3.2 и умеет делить перекошенные партиции в джойнах, но соление ключей иногда приходится делать руками;
- потоки: в Kafka единица параллелизма это партиция, и в обычной группе консьюмеров больше экземпляров, чем партиций, ставить бесполезно;
- хранилище: реплики на чтение, вынос аналитики из OLTP в колоночную базу вроде ClickHouse, материализованные витрины, онлайн-хранилище признаков отдельно от офлайна;
- деградация: лимиты на входе, очередь вместо синхронного ответа, более лёгкая модель как запасной вариант.
Вертикальное масштабирование не стыдно назвать первым шагом: оно дешёвое по времени команды и покупает время на правильное решение. Хорошо закончить примером из своей практики с реальными цифрами.
Где спотыкаются
Сразу предлагают «добавить серверов» без замеров. Если упирается база, десять реплик сервиса только добавят ей соединений и нагрузки.
Добавляют консьюмеров сверх числа партиций топика и удивляются, что отставание не уменьшается.
Не видят перекоса: одна задача в Spark обрабатывает львиную долю данных, и новые экзекьюторы простаивают.