计算资源争抢处理
场景描述
早上 9 点是数仓任务高峰期,多个团队的 Spark/Hive 任务同时抢资源,导致核心任务延迟。
问题表现
| 表现 | 说明 |
|---|---|
| 任务排队 | YARN 队列 Pending Applications 持续增长 |
| 执行变慢 | Container 分配不到足够资源 |
| 核心延迟 | 日报任务本来 1 小时,现在 3 小时 |
| OOM 增多 | 内存不足导致 Container 被 kill |
解决方案
1. YARN 队列资源隔离
root (100%)
├── core (40%) # 核心任务:日报、指标计算
│ ├── min: 40% # 最低保障
│ └── max: 60% # 最高可弹性使用
├── analysis (30%) # 分析师 ad-hoc 查询
│ ├── min: 20%
│ └── max: 40%
├── ml (20%) # 机器学习训练任务
│ ├── min: 10%
│ └── max: 30%
└── default (10%) # 其他
├── min: 5%
└── max: 20%
2. 任务优先级
| 优先级 | 任务类型 | 调度时间 | 队列 |
|---|---|---|---|
| P0 | 核心报表 ETL | 凌晨 2-6 点 | core |
| P1 | 业务指标计算 | 凌晨 6-8 点 | core |
| P2 | 分析师查询 | 白天按需 | analysis |
| P3 | 模型训练 | 错峰(晚间) | ml |
3. 错峰调度
# Airflow 调度优化
# 核心任务:凌晨 2 点开始,避开高峰
schedule_interval = "0 2 * * *"
# 分析型任务:上午 10 点后(核心任务完成后)
schedule_interval = "0 10 * * *"
# 模型训练:晚上 22 点(资源空闲时)
schedule_interval = "0 22 * * *"
4. 资源使用优化
-- 限制 Spark 任务资源使用
SET spark.executor.instances = 10; -- 控制 executor 数量
SET spark.executor.memory = 4g; -- 控制单个 executor 内存
SET spark.dynamicAllocation.enabled = true; -- 动态资源分配
SET spark.dynamicAllocation.maxExecutors = 50; -- 最大 executor 上限
常见面试问题
Q1: 如何评估集群是否需要扩容?
答案:
看以下指标:
- 队列等待时间:Pending 任务平均等待 > 10 分钟
- 资源利用率:集群 CPU / 内存使用率持续 > 80%
- SLA 达成率:核心任务 T+1 出数率低于 95%
- 业务增长:数据量月增长 > 20%
如果以上多项不达标,考虑扩容。
Q2: 扩容太贵,有没有其他办法?
答案:
- 优化 SQL:减少全表扫描,用分区裁剪
- 调度错峰:非核心任务推迟到空闲时段
- 弹性伸缩:云环境下高峰期临时加机器,低峰期释放
- 清理僵尸任务:定期清理不再使用的定时任务
- 数据治理:清理过期数据,减少存储和计算量