hadoop-0.21.0 源码中是这样的:
首先看看 org.apache.hadoop.mapred.TaskTracker 类:
=====================================================================================
> 两个类变量 maxMapSlots 和 maxReduceSlots:
-------------------------------------------
maxMapSlots = conf.getInt(TT_MAP_SLOTS, 2);
maxReduceSlots = conf.getInt(TT_REDUCE_SLOTS, 2);
其中
public static final String TT_MAP_SLOTS = "mapreduce.tasktracker.map.tasks.maximum";
public static final String TT_REDUCE_SLOTS = "mapreduce.tasktracker.reduce.tasks.maximum";
-------------------------------------------
> 类方法 initializeMemoryManagement() 中 ,根据 slots 来决定申请内存的大小
-------------------------------------------
totalMemoryAllottedForTasks =
maxMapSlots * mapSlotMemorySizeOnTT + maxReduceSlots
* reduceSlotSizeMemoryOnTT;
-------------------------------------------
> 类方法 TaskTracker.initialize() 中会起两个 TaskLauncher 线程,分别负责启动 Mapper 和 Reduce 任务:
-------------------------------------------
mapLauncher = new TaskLauncher(TaskType.MAP, maxMapSlots);
reduceLauncher = new TaskLauncher(TaskType.REDUCE, maxReduceSlots);
-------------------------------------------
=====================================================================================
再看看 org.apache.hadoop.mapred.TaskTracker.TaskLauncher 类,它负责启动 Mapper/Reducer 任务。
=====================================================================================
> 初始化 TaskLauncher 时,需要传入 slots 的数量:
-------------------------------------------
public TaskLauncher(TaskType taskType, int numSlots) {
... ...
this.maxSlots = numSlots;
this.numFreeSlots = new IntWritable(numSlots);
... ...
}
特别要注意 numFreeSlots 这个类变量:
private IntWritable numFreeSlots;
-------------------------------------------
> TaskLauncher.run() 中,循环地看是否有新的 Task 需要启动,并且看是否有足够的 slots 可用:
-------------------------------------------
while () {
while (numFreeSlots.get() < task.getNumSlotsRequired()) {
.......
}
numFreeSlots.set(numFreeSlots.get() - task.getNumSlotsRequired()); // 用完了就减掉
}
-------------------------------------------
> Task 执行完了以后,需要释放 slots :
-------------------------------------------
public void addFreeSlots(int numSlots) {
... ...
numFreeSlots.set(numFreeSlots.get() + numSlots);
... ...
}
-------------------------------------------
=====================================================================================
所以,综合上面看,
slots 只是一个逻辑值 ( org.apache.hadoop.mapred.TaskTracker.TaskLauncher.numFreeSlots ),而不是对应着一个线程或者进程。TaskLauncher 会维护这个值,以保证资源使用在控制范围内。
帮助理解的最主要的代码可见 : org.apache.hadoop.mapred.TaskTracker.TaskLauncher.run() 。
Mapper 和 Reducer 都是单独的进程,但是它们与 slots 的关系是这样的:
-------------------------------------------
org.apache.hadoop.mapred.TaskTracker.TaskLauncher.run() {
... ...
//got a free slot. launch the task
startNewTask(tip);
... ...
}
-------------------------------------------
这里的 slots 有点类似 “令牌” 的感觉:申请资源,先获得令牌;释放资源,交还令牌。