2.2 数据本地性 本节摘要:数据本地性指调度器尽量把 Map 任务分配到其输入分片所在的节点上执行,从而避免搬运数据。本地性分节点本地、机架本地、跨机架三级,级别每降一级,代价从内存读取跌落到跨机架网络传输。本节量化这三级差异,解释调度器"等多久才放弃本地性"的权衡,并给出保住本地性的工程做法。 一笔传输账 设一个 128MB 的分片,三种放置方式下 Map 任务读入数据的路径: 节点本地:数据就在执行节点磁盘/页缓存。走本地磁盘读,热数据直接命中内存,典型吞吐数百 MB/s 以上; 机架本地:数据在同机架另一节点。走一次机架内交换机,千兆网卡理论 125MB/s,实际打八折约 100MB/s,读 128MB 约 1.3 秒; 跨机架:数据在别的机架。
本节摘要:数据本地性指调度器尽量把 Map 任务分配到其输入分片所在的节点上执行,从而避免搬运数据。本地性分节点本地、机架本地、跨机架三级,级别每降一级,代价从内存读取跌落到跨机架网络传输。本节量化这三级差异,解释调度器"等多久才放弃本地性"的权衡,并给出保住本地性的工程做法。
设一个 128MB 的分片,三种放置方式下 Map 任务读入数据的路径:
看似秒级差距不大,但乘上规模就吓人:一个 10TB 的作业有一万多个分片,若全部跨机架读,仅输入传输就要消耗十TB 的网络流量,核心交换机直接打满,作业时长被网络钉死。而全部节点本地的作业,网络几乎只为 Shuffle 服务。这就是"移动计算比移动数据便宜"的量化含义:把几十 MB 的程序与任务描述发过去,比把 128MB 的数据拉过来划算,数据再大点差距更悬殊。
HDFS 的副本策略天然配合本地性:默认三副本,两份在同机架不同节点、一份在别的机架。调度器因此通常有三次机会把任务放到数据附近。
调度器为每个待运行任务维护本地性等级,理想顺序:

问题来了:若数据所在节点全部繁忙,调度器是死等,还是把任务发到空闲节点上去拉数据?
Hadoop 的答案是延迟调度:任务先在本地队列里等一小段(可配,默认秒级),若窗口内目标节点释放了槽位就本地执行;等超时了就降级——先试机架本地,再不行跨机架。这个看似简单的策略在论文层面被证明能用很小的等待代价换回绝大部分本地性收益,因为 Map 任务数量众多、单个任务时长有限,槽位很快会轮转出来。
工程上判断本地性是否健康,看作业计数器里的这几个指标:节点本地命中的容器数、机架本地命中数、跨机架数。一个健康的大作业,绝大多数 Map 任务应落在前两档。
注意本地性讨论几乎只围绕 Map 任务。原因在结构上:
这也是第 4 章 Shuffle 被称为"不可避免的恶"的根源之一:Map 端本地性做得再好,第三幕的网络传输量依然由中间数据总量决定。Reduce 端本地性能做的是次要优化。
丢掉本地性的情形:
保住本地性的做法:
回看上一节:分片默认等于块大小,一个分片的数据恰好集中在一个块上,本地性目标明确。若你把分片调成 300MB 而块仍是 128MB,一个分片横跨三个块(可能分属三个节点),任务无论放在哪个节点都得跨网拉另外两块——调分片大小的同时,实际上也在稀释本地性。这是 splitSize 公式里那个 min blockSize 约束的深层理由,也是"想加大分片就同时加大块"这条经验法则的出处。
数据就位、任务开机,下一节补上第一幕的最后一个决策:压不压缩、怎么压。