Как решали вопрос приоритезации раздачи ресурсов в распределенных системах?

«Как решали вопрос приоритезации раздачи ресурсов в распределенных системах?» — вопрос из категории Распределенные системы, который задают на 33% собеседований Data Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В распределенных системах, таких как кластеры для обработки данных, приоритезация ресурсов — это баланс между справедливостью и эффективностью. Я работал с этим на нескольких уровнях:

1. Уровень планировщика ресурсов (YARN/Kubernetes)

  • Очереди с весами: В YARN Capacity Scheduler мы настраивали очереди (например, prod, dev, batch) с гарантированной долей ресурсов (capacity) и максимальной (maxCapacity). Критичные production-задачи отправлялись в очередь prod, которая имела приоритет и гарантированные ресурсы.
  • Ярлыки (labels) в Kubernetes: Для Spark-on-K8S использовали node selectors и tolerations, чтобы направлять важные джобы на выделенную группу нод с большими ресурсами, изолируя их от менее важных нагрузок.

2. Уровень фреймворка (Apache Spark)

  • Режим планировщика FAIR: Включал его для пулов внутри Spark-приложения.
    spark.conf.set("spark.scheduler.mode", "FAIR")
    spark.conf.set("spark.scheduler.allocation.file", "/path/to/fair-scheduler.xml")

    В файле конфигурации определял пулы (например, high_priority, low_priority) с весами (weight) и минимальными долями ресурсов (minShare). Долгосрочные ETL-задачи запускались в пуле с низким весом, а интерактивные аналитические запросы — в пуле с высоким весом, получая ресурсы быстрее.

3. Уровень оркестратора задач (Apache Airflow)

  • Пуллы (Pools): Ограничивали количество параллельно выполняемых "тяжелых" задач (например, загрузки в витрины), чтобы не перегрузить кластер. Критичным DAG назначался отдельный пул с большим слотом.
    default_args = {
        'pool': 'critical_pool',
        'priority_weight': 15
    }

Общий принцип: Критичные для бизнеса пайплайны (например, ежедневное формирование финансового отчета) получали гарантированные ресурсы через выделенные очереди и высокий вес. Фоновые, исследовательские или тестовые задачи выполнялись по остаточному принципу, что позволяло максимально утилизировать кластер без ущерба для SLA.