调度策略基础:FIFO、公平调度、容量调度的原理与对比
调度策略这东西,说白了就是「谁先拿资源」的规则。我刚开始做集群管理时,觉得调度嘛,不就是排队?后来被现实狠狠教育了一顿。你想想看,一个 Hadoop 集群几百台机器,任务五花八门,要是调度策略选错了,轻则资源浪费,重则线上事故。
今天咱们就聊聊三种最基础的调度策略:FIFO、公平调度和容量调度。嗯,别看它们老,但理解透了,后面学 YARN、Kubernetes 调度会轻松很多。
一、FIFO 调度:先来先服务
FIFO,全称 First In First Out,先进先出。这应该是人类最直观的调度方式了——谁先提交任务,谁就先拿资源。
核心思想:一个全局队列,任务按提交时间排序。前面的任务不跑完,后面的只能等着。
我在项目中遇到过一个小团队,他们用 Hadoop 跑离线报表,数据量不大,FIFO 用得好好的。后来业务扩张,报表任务和临时查询混在一起,问题就来了——一个跑 2 小时的报表堵住队列,后面 5 分钟的临时查询硬生生等了 1 小时 50 分钟。
FIFO 的优缺点:
- 优点:实现简单,逻辑清晰,适合小规模、任务类型单一的集群。
- 缺点:容易产生「队头阻塞」——一个大任务卡住,后面所有小任务都得等。
避坑指南:我曾经在一个 20 节点的集群上用过纯 FIFO,结果一个 Spark 任务把内存吃光了,后面 MapReduce 任务全部 OOM。后来我学乖了——FIFO 只适合「任务大小差不多」的场景,否则一定要加资源限制。
二、公平调度(Fair Scheduling):雨露均沾
公平调度,顾名思义,就是让每个任务都能分到资源。它不像 FIFO 那样死板,而是动态调整——任务多就每人分一点,任务少就让某个任务多吃点。
为什么会这样?因为公平调度引入了「最小保证」的概念。每个任务池(Pool)都有一个最低资源保障,比如 20% 的 CPU。即使其他任务再多,这个池也能拿到至少 20%。
核心机制:公平调度器会定期计算每个任务的「资源缺口」——当前资源与应得资源的差距。缺口越大的任务,优先级越高。
我记得有一次帮客户调优,他们 100 个节点跑着 3 个部门的任务。用 FIFO 时,A 部门的大任务经常把 B、C 部门的小任务饿死。换成公平调度后,每个部门至少能拿到 30% 的资源,虽然大任务跑得慢了,但整体满意度反而高了。
公平调度的关键参数:
minimum:每个池的最小资源保障maximum:每个池的最大资源上限weight:权重,权重高的池在资源竞争时能分到更多
个人经验:公平调度适合多租户场景。但要注意——如果所有池都设了很高的 minimum,集群资源不够分时,调度器会陷入「死锁」,谁也跑不动。我建议 minimum 总和不要超过集群总资源的 80%。
三、容量调度(Capacity Scheduling):分田到户
容量调度和公平调度有点像,但思路更「硬」。它把集群切成多个「队列」,每个队列有固定的容量上限。比如队列 A 占 50%,队列 B 占 30%,队列 C 占 20%。
你想想看,这就像分田到户——每家分一块地,你家地里的活再多,也不能占邻居的地。除非邻居的地闲着,你才能临时借用一下。
核心区别:公平调度是「动态平衡」,容量调度是「静态划分」。容量调度更强调隔离性——一个队列的任务再疯狂,也不会影响其他队列。
我在金融行业见过一个典型场景:生产队列和测试队列共用集群。用容量调度,生产队列占 70%,测试队列占 30%。测试任务再浪,也最多吃掉 30% 的资源,生产任务稳如泰山。
容量调度的核心概念:
- 容量(Capacity):队列保证能拿到的资源百分比
- 最大容量(Maximum Capacity):队列最多能拿到的资源百分比(防止借太多)
- 弹性(Elasticity):队列空闲时,资源可以借给其他队列
注意:我曾经遇到一个坑——容量调度下,如果队列 A 的容量是 50%,但它的任务很少,队列 B 借走了 30%。突然队列 A 来了个大任务,需要立刻收回资源。这时队列 B 的任务会被强制杀死!所以「弹性」一定要配合「抢占(Preemption)」机制使用,否则会出事故。
四、三种策略的对比
说了这么多,咱们用一张表来总结:
| 特性 | FIFO | 公平调度 | 容量调度 |
|---|---|---|---|
| 资源分配方式 | 顺序分配 | 动态平衡 | 静态划分 |
| 任务隔离性 | 无 | 弱(可借用) | 强(有上限) |
| 适用场景 | 小集群、单用户 | 多租户、负载波动大 | 多租户、需要强隔离 |
| 实现复杂度 | 低 | 中 | 高 |
| 典型代表 | Hadoop 1.x 默认 | YARN Fair Scheduler | YARN Capacity Scheduler |
五、核心逻辑流程图
下面这张 SVG 图展示了三种调度策略的核心逻辑。我画的时候特意把「队列」和「资源池」的关系标出来了,你一看就明白。
六、如何选择?
说实话,没有「最好」的调度策略,只有「最合适」的。我个人的选择经验是这样的:
- 集群小于 10 节点,任务类型单一:FIFO 就够了,别折腾。
- 多部门共用集群,任务大小不一:公平调度,灵活且公平。
- 生产环境,需要强隔离:容量调度,稳字当头。
一个小技巧:如果你不确定选哪个,可以先从公平调度开始。它最灵活,后期可以平滑迁移到容量调度。我在好几个项目里都是这么干的——先用公平调度跑一段时间,观察资源使用模式,再决定要不要切到容量调度。
嗯,调度策略的基础就聊到这儿。这三种策略是后续学习 YARN、Kubernetes 调度的基石。你想想看,理解了「先来后到」「公平分配」「容量隔离」这三个核心思想,后面那些花里胡哨的调度器,本质上都是它们的变体或组合。