Hadoop中Mapper和Reducer是单独进程还是线程
来源:互联网 发布:网络神曲 编辑:程序博客网 时间:2024/05/19 19:44
hadoop一个节点默认起两个map slot,请问这两个slot是多线程吗?
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 有点类似 “令牌” 的感觉:申请资源,先获得令牌;释放资源,交还令牌。
mapper 和 reducer 都是单独的进程?好像有点不对,是单独的线程吧?是单独的进程。
启动Mapper/Reducer的总的调用路径是:
org.apache.hadoop.mapred.TaskTracker.TaskLauncher.run()->org.apache.hadoop.mapred.TaskTracker.startNewTask()->org.apache.hadoop.mapred.TaskTracker.launchTaskForJob()->org.apache.hadoop.mapred.TaskTracker.TaskInProgress.launchTask()?->org.apache.hadoop.mapred.Task.createRunner() // 抽象方法,具体实现在子类 MapTask 和 ReduceTask 中
org.apache.hadoop.mapred.MapTask.createRunner() // 创建 MapTaskRunner 类实例
org.apache.hadoop.mapred.ReduceTask.createRunner() // 创建 ReduceTaskRunner 类实例
最终,跟踪到了 MapTaskRunner 和 ReduceTaskRunner 这两个类。
至此,我们看看它们的父类 org.apache.hadoop.mapred.TaskRunner ,以下是类的说明:
/** Base class that runs a task in a separate process. Tasks are run in a separate process in order to isolate the map/reduce system code from bugs in user supplied map and reduce functions.?*/
TaskRunner 虽然 extends Thread (看起来是个线程),但是真正启动Mapper和Reduce进程的代码在函数 TaskRunner.run() 中:
public final void run() {... ...
launchJvmAndWait(setup, vargs, stdout, stderr, logSize, workDir, env);... ...
}
其调用了 TaskRunner.launchJvmAndWait() 方法(在此之前还有些创建文件夹、设置配置参数和环境变量等准备性的操作):
void launchJvmAndWait(List<String> setup, Vector<String> vargs, File stdout,File stderr, long logSize, File workDir, Map<String, String> env)throws InterruptedException {jvmManager.launchJvm(this, jvmManager.constructJvmEnv(setup, vargs, stdout,stderr, logSize, workDir, env, conf));synchronized (lock) {while (!done) {lock.wait();}}}
上面代码主要是 launch 一个 java虚拟机进程。这也是Hadoop启动代价很高的原因,因为launch虚拟机是比较耗资源的;于是又提供了Task JVM Reuse机制。
单独起进程的原因也说得很清楚,就是: isolate the map/reduce system code from bugs in user supplied map and reduce functions。其实就是,通过使用不同的进程空间,进行隔离,防止用户提供的代码中有bug死掉后,造成 TaskTracker 所在进程也死掉(这个死掉了,效果就跟阿凡达里面的发光树被毁了一样)。
Hadoop-0.20.2源码中的实现基本也是差不多的。
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 有点类似 “令牌” 的感觉:申请资源,先获得令牌;释放资源,交还令牌。
mapper 和 reducer 都是单独的进程?好像有点不对,是单独的线程吧?是单独的进程。
启动Mapper/Reducer的总的调用路径是:
org.apache.hadoop.mapred.TaskTracker.TaskLauncher.run()->org.apache.hadoop.mapred.TaskTracker.startNewTask()->org.apache.hadoop.mapred.TaskTracker.launchTaskForJob()->org.apache.hadoop.mapred.TaskTracker.TaskInProgress.launchTask()?->org.apache.hadoop.mapred.Task.createRunner() // 抽象方法,具体实现在子类 MapTask 和 ReduceTask 中
org.apache.hadoop.mapred.MapTask.createRunner() // 创建 MapTaskRunner 类实例
org.apache.hadoop.mapred.ReduceTask.createRunner() // 创建 ReduceTaskRunner 类实例
最终,跟踪到了 MapTaskRunner 和 ReduceTaskRunner 这两个类。
至此,我们看看它们的父类 org.apache.hadoop.mapred.TaskRunner ,以下是类的说明:
/** Base class that runs a task in a separate process. Tasks are run in a separate process in order to isolate the map/reduce system code from bugs in user supplied map and reduce functions.?*/
TaskRunner 虽然 extends Thread (看起来是个线程),但是真正启动Mapper和Reduce进程的代码在函数 TaskRunner.run() 中:
public final void run() {... ...
launchJvmAndWait(setup, vargs, stdout, stderr, logSize, workDir, env);... ...
}
其调用了 TaskRunner.launchJvmAndWait() 方法(在此之前还有些创建文件夹、设置配置参数和环境变量等准备性的操作):
void launchJvmAndWait(List<String> setup, Vector<String> vargs, File stdout,File stderr, long logSize, File workDir, Map<String, String> env)throws InterruptedException {jvmManager.launchJvm(this, jvmManager.constructJvmEnv(setup, vargs, stdout,stderr, logSize, workDir, env, conf));synchronized (lock) {while (!done) {lock.wait();}}}
上面代码主要是 launch 一个 java虚拟机进程。这也是Hadoop启动代价很高的原因,因为launch虚拟机是比较耗资源的;于是又提供了Task JVM Reuse机制。
单独起进程的原因也说得很清楚,就是: isolate the map/reduce system code from bugs in user supplied map and reduce functions。其实就是,通过使用不同的进程空间,进行隔离,防止用户提供的代码中有bug死掉后,造成 TaskTracker 所在进程也死掉(这个死掉了,效果就跟阿凡达里面的发光树被毁了一样)。
Hadoop-0.20.2源码中的实现基本也是差不多的。
- Hadoop中Mapper和Reducer是单独进程还是线程
- Hadoop Mapreduce Mapper和Reducer源码
- hadoop中槽-slot是线程还是进程讨论
- hadoop中槽-slot是线程还是进程讨论
- Hadoop中的进程与Mapper实例,Reducer实例
- Hadoop中map/reduce编程中关于mapper和reducer的Format问题
- hadoop中map/reduce编程中关于mapper和reducer的Format问题
- Hadoop中map/reduce编程中关于mapper和reducer的Format问题
- Hadoop mapper类和reducer类的阅读 Hadoop(1)
- Hadoop-Mapper-Reducer文档学习
- Hadoop开发周期(二):编写mapper和reducer程序
- hadoop学习-Mapper和Reducer的输出类型
- Hadoop学习之传递命令行参数给Mapper和Reducer
- Hadoop-2.4.1学习之Mapper和Reducer
- Hadoop-2.4.1学习之Mapper和Reducer
- Hadoop-2.4.1学习之Mapper和Reducer
- hadoop 多个Mapper和Reducer的Job
- MapReduce中Mapper类和Reducer类4函数解析
- ERROR OGG-00222 及查看是否开启DDL
- Win7 X32MyEclipse10.1破解
- 大话存储系列19——数据备份与恢复 下
- 计算机经典书籍
- 网站开发人员应该知道的61件事
- Hadoop中Mapper和Reducer是单独进程还是线程
- 错误纠正(Error Correction)
- Android常见错误解决
- c++多线程编程
- DB9接口说明
- hdu 1159 Common Subsequence
- Flex 与java通信的三种方式
- 学习笔记——JavaScript中的Array对象
- Android学习笔记---29_构建soap协议内容,发送xml数据和调用webservice,手机号码归属地查询器